當前位置:首頁 » 文件傳輸 » jvm句柄訪問教學
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

jvm句柄訪問教學

發布時間: 2023-04-19 12:06:10

⑴ 技能篇:linux服務性能問題排查及jvm調優思路

vmstat 和 pidstat。vmvmstat 可查看系統總體的指標,pidstat則詳細到每一個進程服務的指標

Swap 其實就是把一塊磁碟空間或者一個本地文件,當成內存來使用。swap 換出拿孫,把進程暫時不用的內存數據存儲到磁碟中,並釋放這些數據佔用的內存。swap 換入,在進程再次訪問這族敏空些內存的時候,把它們從磁碟讀到內存中來

當一個網路幀到達網卡後,網卡兆瞎會通過 DMA 方式,把這個網路包放到收包隊列中;然後通過硬中斷,告訴中斷處理程序已經收到了網路包。接著,網卡中斷處理程序會為網路幀分配內核數據結構(sk_buff),並將其拷貝到 sk_buff 緩沖區中;然後再通過軟中斷,通知內核收到了新的網路幀。內核協議棧從緩沖區中取出網路幀,並通過網路協議棧,從下到上逐層處理這個網路幀

⑵ JROCKIT 5.0——輕松玩轉JVM

BEA JRockit Java虛擬派指脊機(JVM)所帶來的不僅僅是性能的提升 本文探討了JRockit R 版本可用的一些管理和使用方面的特性 概述了JRockit Mission Control分析工具套件 JRockit Management Console的試驗性headless模式以及使用Ctrl Break Handler JRCMD 堆視圖和code coverage與JVM進行交互

簡介JRockit JVM不只是快 它還和JRockit Mission Control一起 組成一套執行運行時分析和內存泄漏檢測的分析工具 JRockit Management Console包含在JRockit JDK中 本文將探討JRockit Management Console的一種試驗性的headless模式 它可以用於與來自命令行的基於JRockitJMX的管理代理進行交互 Ctrl Break Handler提供了一種向JRockit發送各種高級命令的方法 甚至是在它啟動後 這些命令甚至可以遠程調用 我在後文中會提及 最後 我探討了試驗性的code coverage JRockit開箱即用地提供了該特性

關於BEA JRockit的更多信息 參見dev dev網站的JRockit Proct Center

首先我將快速概述一下JRockit JVM可用的已確定的管理工具 然後我會轉向缺少文檔的試驗性管理特性

JRockit Mission ControlJRockit R 版本引入了JRockit Mission Control工具套件 它包含的工具可以進行監控 管理 分析和消除Java應用程序內存泄漏 而不會引起通常與此類工具相關聯的性能開銷 Mission Control的低性能開銷是因為使用了作為JRockit常規適應性動態調優的一部分而收集的數據 這還可以消除工具使用位元組碼裝置修改系統執行特性時發生Heisenberg異常的問題 JRockit Mission Control功能可以根據需要隨時可用 低性能開銷也只在運行工具時有效 這些特徵使得JRockit Mission Control成為專門用於生產中系統的工具

JRockit Mission Control中包含以下工具

JRockit Management ConsoleJRockit Management Console用於監逗衡控和管理多個JRockit實例 它捕獲並顯示關於垃圾收集器(GC)暫停 內存和CPU使用的實時數據 以及部署在JVM內部MBean伺服器上的所有JMX MBean的信息 JVM管理包括塵滲對CPU相似性 垃圾收集策略和內存池大小的動態控制 JRockit Runtime AnalyzerJRockit Runtime Analyzer(JRA)是一個隨需應變的 動態記錄器 它生成關於JVM和正在運行的應用程序的詳細記錄 然後可以使用JRA應用程序對記錄下來的配置文件進行離線分析 所記錄的數據包括對方法和鎖定的分析 還有垃圾收集統計信息 優化決策以及對象統計信息 JRockit Memory Leak DetectorJRockit Memory Leak Detector工具用來發現和查找內存泄漏原因 Memory Leak Detector的趨勢分析器可以發現非常緩慢的泄漏 顯示詳細的堆統計信息(包括指向泄漏對象和分配位置的引用類型和實例) 並快速找出泄漏原因 Memory Leak Detector使用先進的圖形化表現技術 以便更容易定位和理解有時比較復雜的信息

關於JRockit Mission Control的更多信息 可以閱讀文章An Introction to JRockit Mission Control 或者訪問dev dev網站的JRockit Mission Control

JRockit Management Console的Headless模式(試驗性)

JRockit Management Console是監控JRockit運行的工具 它包括兩部分 一個運行在JVM進程中的JMX代理 一個使用圖形化用戶界面的獨立客戶端(關於它以及其它方面的更詳細的信息 請參見An Introction to JRockit Mission Control) 其中 用戶界面可以繪出部署在所連接的Java虛擬機中的任何MBean的數值屬性的圖形 圖形密集的應用程序對資源的消耗可能會相當厲害 JRockit Management Console也不例外 可以引入text only(純文本)模式 以便使用Management Console的通知功能和數據收集工具而不會導致整個GUI的開銷

headless控制台引入了大量新的命令行參數 這同樣適用於控制台的GUI版本 參數包括

參數 描述 headless 以headless模式啟動控制台(不會載入與GUI相關的類) settings <settings file> 使用指定配置文舳H綣訥UI模式啟動 並且該文件不存在 那麼它將在關閉Management Console時創建 connectall 連接配置文件中所有可用連接(即原先使用GUI添加的) connect <connection > <connection > < > 使用GUI連接配置文件中可用的指定連接 autoconnect 自動連接到運行在啟用JRockit發現協議(JRockit Discovery Protocol JDP)的管理伺服器上的任何JRockit uptime <time in seconds> 將控制台運行一段指定的時間 然後自動關閉它 useraction <name> <delay in seconds> <period (optional)> 經過指定的時延後運行指定的用戶動作 如果不指定period 動作將只執行一次 如果指定 動作將每過<period>秒就執行一次 version 列印Management Console的版本信息 並退出 locale <language> <country (optional)> 使用特定的地區啟動控制台 比如 locale ja JP將以日語啟動控制台(JRockit R 可用)

這里給出一個以headless模式啟動Management Console的例子 讀取指定配置文件 嘗試連接所有已指定的JRockit 使用JRockit發現協議(JDP 下文討論)積極查找新的JRockit 秒後將以每分鍾一次的間隔向所有連接的JRockit發送Ctrl Break命令 一小時之後自動關閉 以前加入指定連接的所有通知規則(不管是通過使用GUI還是通過直接編輯配置文件添加的)將生效

java jar ManagementConsole jar headless settings C:Headlessconsolesettings xml connectall autoconnect uptime useraction ctrlbreak

用戶動作是可以與JRockit Management Console上的一組連接進行交互的插件類 同樣使用控制台配置文件來存儲配置數據 用戶動作顯示在JRockit控制台圖形用戶界面的Plugins菜單下 headless模式中也可用 隨控制台提供了兩個默認用戶動作 jrarecording用戶動作 對連接的JRockit啟動JRA記錄 ctrlbreak用戶動作 向連接的JRockit發送Ctrl Break命令(參見本文中關於Ctrl Break Handler和JRockit運行時分析器的小節) 要指定特定用戶動作的參數 可以使用GUI進行配置 也可以編輯Management Console配置文件 後者可以在<user home>/ManagementConsole/ManagementConsole/consolesettings <version> xml文件中找到

編寫自己的用戶動作很容易 首先創建一個AbstractUserAction的子類 該示例演示了如何創建一個從所有連接的JRockit獲取線程堆棧轉儲的用戶動作

package example useractions; import java io IOException; import java util List; import nsole rjmx CommonRJMXNames; import nsole rjmx RJMXConnectorModel; import nsole useractions AbstractUserAction; /** * This is a simple user action getting stackmps from * the selected JRockits and printing them on stdout * * @author Marcus Hirt */ public class MyUserAction extends AbstractUserAction { public void executeAction(List connections) { for (RJMXConnectorModel connection : connections) { if (connection isConnected()) { try { System out println(CommonRJMXNames getThreadMXBean(connection) getThreadStackDump()); } catch (IOException e) { e printStackTrace(); } } } } }

接下來 需要在consolesettings xml文件中配置部屬描述符 以便用戶動作對於控制台可用 可以在配置文件中發現user_actions元素 它已經填充了一些user_action元素 示例動作的部署描述符應當以相同的樣式輸入 描述符看起來會是這樣

<user_action> <user_action_class> example useractions MyUserAction</user_action_class> <user_action_name>stackmp</user_action_name> <user_action_menu_name>Stack Dump on stdout</user_action_menu_name> <user_action_description>Gets a stack mp from the selected JRockit(s) and mps it on stdout </user_action_description> </user_action>

這也使得用戶動作在Plugins菜單下的用戶界面中可見

當控制台啟動或退出時 如果有設置/狀態需要從配置文件載入/保存 只需重寫exportToXml()/importFromXml()方法 如示例中所示

/** * @see nsole util XmlEnabled * #exportToXml( w c dom Element) */ public void exportToXml(Element parentNode) { super exportToXml(parentNode); XmlToolkit setSetting(parentNode MY_PROPERTY m_myVal); } /** * @see nsole util XmlEnabled * #initializeFromXml( w c dom Element) */ public void initializeFromXml(Element parentNode) { super initializeFromXml(parentNode); m_myVal = XmlToolkit getSetting(parentNode MY_PROPERTY DEFAULT_MY_VALUE)); }

注意 用戶動作的名稱是使用launcher啟動參數時將引用的用戶動作名稱 菜單名是會在GUI菜單中顯示的名稱 更多的信息請參見user action docs和JLMEXT docs 注意 這只是一個試驗性的功能 提供的文檔還相當簡單 編寫定製的通知動作和約束的方式與此類似 更多信息請參見Management Console User Guide

JRockit發現協議(JDP)JDP(JRockit發現協議)是個簡單且有效的協議 用於允許JRockit管理伺服器向Management Console組播它的存在 下面的兩個表分別列出了在伺服器端和客戶端控制JDP行為的系統屬性

管理伺服器的JDP屬性 系統屬性 描述 默認值 jrockit managementserver autodiscovery 啟用JRockit發現協議 False jrockit managementserver discovery period 在兩個ping之間需要等待多久(以毫秒為單位) jrockit managementl 活躍的躍點數 jrockit managementserver discovery address 所使用的組播地址 jrockit managementserver discovery port 所使用的組播埠

Management Console的JDP屬性 系統屬性 描述 默認值 nsole preferences jdp port 用於JRockit發現協議的埠 nsole preferences jdp address 所使用的組播地址

這里給出了在伺服器端啟用JDP的情況下 啟動JRockit需要最少參數的示例

java Xmanagement Djrockit managementserver autodiscovery=true<your program>

Ctrl Break Handler

您是否曾經希望在JVM啟動後可以使用一種輕松的方式與其交互?假如說您忘記添加 Xmanagement選項來啟動管理伺服器 或者您想改變運行系統中GC的冗餘級別 這些現在很容易通過重新配置Ctrl Break Handler來完成 而且它不只是列印堆棧跟蹤

用法

創建一個名為ctrlhandler act的文件 向ctrlhandler act文件添加命令(參見下文命令列表) 以 stop 結束文件 這是結束文件分析的保留命令 按下ctrl break 每一個命令都將以出現的順序執行

JRockit首先會在當前工作目錄查找該文件 如果未找到 JRockit將在JVM目錄中查找 如果仍然沒有的話 JRockit將回退以生成一個常規的線程堆棧轉儲 JRockit將在每次按下ctrl break時讀取act文件 因此用戶可以在方便時重新配置該文件 而同時JRockit仍在運行

這里給出一個示例act文件 它首先列印時間戳 然後是用於啟動JRockit的命令行 最後是一個線程堆棧轉儲 它還包括可以用於act文件的有用命令的列表

# Example ctrlhandler act file timestamp mand_line print_threads stop # set_filename filename=<file> [append=true] # Sets the file that all handlers following this mand will # use for printing You can have several set_filename mands # in a file It takes o arguments: filename and an optional # append to specify if you want to append to the file # or overwrite it Default is to overwrite the file # timestamp # Prints a timestamp # print_threads # The normal thread mp # verbosity [args=<ponents>] [filename=<file>] # Changes the verbosity level normally specified with Xverbose # version # Prints JRockit version information # mand_line # Prints the mand line used to start JRockit # print_object_summary # Prints heap usage statistics (how much heap is used per class) # together with a delta on how much this has changed since # the last invocation of this ctrl break handler # print_memusage # Prints a memory usage report of how JRockit is using # the memory # heap_diagnostics # Prints a detailed report of the heap including ascii graphics # over the heap layout # print_class_summary # Prints all loaded classes # print_utf pool # Print all UTF strings # jrarecording [filename=<file>] [time=<time>] [nativesamples=true] # Starts a JRA recording # run_optfile [filename=<file>] # See OptFile # start_management_server # Starts the new JMX based management agent # kill_management_server # Stops the management agent # start_rmp_server # Starts the old management server (actually the listening # socket that in turn starts servers whenever a connection # is established) # kill_rmp_server # Stops the old management server (actually shuts down the # listening socket) The only reason it isn t named # kill_rmp_server is that stop is a reserved keyword # that stops the parsing of the act file ;) # help [ctrl break handler] # Prints all available ctrl break handlers if no argument # is specified or help for the specified ctrl break handler # memleakserver [port=<port>] # Toggles the memleakserver If it hasn t been started # it will be started If it has already started it will be # shut down The default port is # verbose_referents action=[heap|full|nursery|start|stop] # Print verbose reference information # Parameters: # action=[heap|full|nursery|start|stop] # heap trigger a heap collection and output reference # information # full trigger a full heap collection (clears softly # reached soft referents) # nursery trigger a nursery collection (heap collection # if running without nursery) # start start writing reference information to default # verbose stream # stop stop writing reference information # print_exceptions # exceptions=[true|all|false] stacktraces=[true|all|false] # Enable printing of Java exceptions thrown in the VM # Parameters: # exceptions print exceptions # stacktraces print exceptions with stacktraces # At least one of the parameters is required # Values for the parameters can be true|all|false # true print all exceptions # except java/util/EmptyStackException # java/lang/ClassNotFoundException and # java/security/PrivilegedActionException # all print all exceptions # false don t print exceptions # To turn exception printing off pletely you need to set # exceptions = false even if it was turned # on by stacktraces = true JRCMD 使用JRCMD實用工具是一種新的調用Ctrl Break Handler的便捷方式 可在JRockit發行版的bin目錄中找到它 用法 jrcmd <PID> <mand> <parameters>

JRCMD使用JRCMD實用工具是一種新的調用Ctrl Break Handler的便捷方式 可在JRockit發行版的bin目錄中找到它

用法 jrcmd <PID> <mand> <parameters>

PID = 要在其中執行Ctrl Break Handler的JRockit進程的進程ID mand = 要執行的Ctrl Break Handler命令 parameters = Ctrl Break Handler的參數

如果不指定選項(或者只指定 P) 那麼將顯示運行在本地機器上的所有JRockit的進程ID 如果PID設為 那麼命令將發送給在本地機器上運行的所有JRockit JVM

要列出特定的JRockit中有哪些Ctrl Break Handler可用 可以使用help命令

jrcmd <PID> help

要想獲得某個具體的Ctrl Break Handler的幫助信息 需要在help後添加Ctrl Break Handler的名稱 比如

jrcmd help kill_management_server

也可以使用JRCMD列出指定進程的性能計數

jrcmd <PID> l

遠程調用Ctrl Break Handler可以使用JRockit Management Console來遠程調用Ctrl Break Handler 存在一個對JRockitConsoleMBean的操作 稱為runCtrlBreakHandlerWithResult JRockit Management Console可以從屬性瀏覽器調用對MBean的操作 這里有關於如何調用Ctrl Break Handler的逐步描述

連接到一個運行中的JRockit 右擊該連接 選擇Browse Attributes 展開 jrockit domain文件夾 選擇JRockitConsole MBean 單擊operations選項卡 查看可用操作 單擊String parameter參數按鈕 找到runCtrlBreakHandlerWithResult操作 輸入希望執行的Ctrl Break Handler名稱 語法與ctrlhandler act文件相同 按下OK 按下Execute按鈕 執行操作

試著輸入 help 作為參數 將會列出所有可用的Ctrl Break Handler 如圖 所示

圖 從JRockit Management Console調用Ctrl Break Handler(單擊圖片查看大圖)

堆視圖(試驗性)當分析應用程序如何使用某種垃圾收集策略時 在每一次GC後對堆進行快照將會非常有幫助 這有助於開發人員研究數據 比如碎片/壓縮以及演算法通常如何執行 但是快照中包含如此多的數據量以至於查看它沒有什麼意義 因此JRockit團隊開發了一個提供圖形化表示的小工具 以便更好地進行說明

圖 顯示了一個快照的例子(使用的是一個非常早的JRockit 預發布版本)

每一排表示一次垃圾收集 左邊是開始的堆 右邊是結束的堆 堆顯示的右邊是一個可配置圖形 實心白 *** 域表示空白堆 黑 *** 域是充實區(也就是填充了對象的區域) 淺灰 *** 域是碎片區 紅色 黃色和綠 *** 域是可配置圖形 可以從命令行指定在可配置圖形中顯示什麼 該工具依然很粗糙 對於用戶也不夠友好 不過毋庸置疑它對JRockit的終端用戶非常有用 所以這是一個非常不錯但是不能通用的工具

code coverage(試驗性)很多開發人員在以某種方式使用他們的應用程序時 使用code coverage分析來研究諸如代碼庫中的多少以及哪些部分正在運行之類的狀況 測試人員喜歡使用code coverage來度量測試套件覆蓋應用程序的比例 但是 對於大型應用程序 由code coverage工具所引起的性能開銷通常是被禁止的

JRockit內置了高性能的行code coverage 當啟用code coverage運行時 代碼將由記錄行命中的捕獲器生成 一旦某行被命中並記錄 就刪除捕獲器 JRockit可以繼續以接近全速的速度運行

要使JRockit記錄code coverage數據 必須指定一個命令行選項

用法 Xcodecoverage

可以使用以下系統屬性來控制該行為

系統屬性 描述 decoverage filter=<filterspec> filterspec是個以分號(Windows)或冒號(Linux)隔開的篩選器字元串列表 它定義哪些類應當被覆蓋 以 開頭的篩選器字元串會被視為不應當覆蓋的類

示例 decoverage filter=java/util/Hashtable;/bea/*; /bea/bla *

decoverage filterfile=<filename> 設置包含篩選器定義的文件的文件名 文件格式為每行一個篩選器字元串 decoverage outputfile=<filename> 設置存放輸出的文件 如果寫入<filename>_ 輸出文件不能被打開 那麼將嘗試<filename>_ 以此類推 在多個JVM共享一個公共命令行的情況中 這可能會很有用 decoverage testid=<id string> 設置初始測試標識符 decoverage verbose 使code coverage更為詳細 適用於在覆蓋文件(均是純文本文件)中執行文本比較 decoverage appendoutput 設置對輸出文件的寫入為追加而不是覆蓋

這里給出特定於code coverage的參數 用於生成如下圖中所示的數據

Xcodecoverage decoverage filter=/jrockit/console/*;/jrockit/mon/* decoverage outputfile=console_coverage txt

在內部 由一個code coverage小工具來解釋JRockit所生成的數據 如圖 所示

圖 code coverage工具的輸出示例

lishixin/Article/program/Java/hx/201311/26298

⑶ jvm如何定位一個對象

1、使用句柄:

如果使用句柄訪問的話,那麼java堆將會劃分出歷晌一塊內存來作為句柄池,reference中存儲的就是對象的句柄地址,而句柄中包含了對象實例數據和類型數據各自的地址信息

優點:使用句柄的最大的好處就是reference中存儲的時穩定的句柄地址,即的對象移動(例如GC垃圾回肢頃鋒收時)時只會改變句柄中的書庫數據的指針,reference本身不需要修改。

2、使用直接指針:

reference中存儲的直接就是對象的地址

優點:直接指針訪問方式最大的好處就是速度快,乎銷他節省了一次指針定位的時間開銷,但是由於對象會經常被訪問,因此這項開銷積少成多後也是一項非常可觀的執行成本

⑷ JVM系列之類的准備與解析

一、前言

每個類的生命周期,和生命一樣,都有起點與終點;
每個類都會在自己的生命周期里,完成自己的使命--使命必達!
類在這個階段,被賦予了它的天賦與使命;

二、准備階段
    為class對象和類元數據信息分配內存空間,並初始化靜態變數和常量值,這里變數使用的內存都在方法區中分配;
這里是初始化僅包括類變數(被static修飾的變數),而不包括實例變數,實例變數將會在對象實例化隨著對象一起分配在Java堆中;

這里所說的初始值「通常情況」下是數據類型的零值,例如:
public static int value=110;

這里value賦的初始值洞飢是0不是110,這時候尚未開始任何Java方法,而把value賦值為110的 putstatic 指令是程序被編譯後,存放於類構造器初始化方法之中,所以把value賦值為110的動作將在初始化階段才會執行;

如果變數是被final關鍵字修飾,那麼准備階段就會被賦值為110,不必等到初始化階段再賦值。

三、解析
    該階段是將jvm虛擬機中常量池的符號引用替換成直接引用,解析動作主要針對類或介面、欄位、類方法、介面方法、方法類型、方法句柄和調用點限定符。

    1、類或介面的解析
        第一步: 如果C不是一個數組類型,那麼虛擬機會把代表N的許可權定名傳遞給D的類載入器去載入這個類C。在載入的過程當中,由於元數據、位元組碼驗證的操作,又可能觸發其它類的載入動作,一旦出險任何異常,則解析宣告失敗;
        第二步:如果C是一個數組類型,並且數組元素為脊顫昌對象,描述符類似「[Ljava/lang/Integer」的形式按照第一點的規則載入數組元素類型。如果N的描述符如前面所假設的形式,需要載入的類型就是java.lang.Integer,接著由虛擬機生成一個代表次數組維度和元素的數組對象;
        第三步:如果上面的步驟沒有任何異常,那麼C在虛擬機中實際上已經稱為一個有效的類或介面了。解析之前還要進行符號驗證,確認D是否具有對C的訪問許可權,如果不具備則會拋出異常。

    2、欄位解析
        對欄位表內class_index項中索引的CONSTANT_Class_info符號引用進行解析,也就是欄位所屬的類或介面的符號引用;
        如果解析這個類或符號引用的過程中出現任何異常,都會導致欄位符號引用解析的失敗;
        如果解析成功,接下來沿著它的父類/父介面尋找是否有這個欄位;
        如果這個過程不出錯,則會在找到符合欄位的時候返回這個欄位的直接引用(如果有會進行許可權驗證,如果不具備許可權則拋出異常)。

    3、類方法解析
        類方法解析首先也要首先解析出類方法表class_index項中索引的方法所屬的類或介面的符號引用;
        1)類方法和介面方法符號引用的常量類型定義是分開的,如果在類方法表中索引類是個介面,直接拋出異常;
        2)如果通過了第一步,在類中查找是否有簡單名稱和描述符都與目標匹配的方法,有則返回這個方法的直接引用;
        3)如果第二步沒找到,則會在類的父類遞歸查找是否有這個方法,有則返回直接引用,或者在類的介面列表和父介面遞歸查找,如果存在匹配的方法,說明類是一個抽象類,拋出異常;
        4)如果還是沒有找到,就是說明該類不存在或不存在在已知路徑中,報錯拋異常。

    4、介面方法解析
        介面方法需要先解析出介面方法表的class_index 項中索櫻扒引的方法所屬的類或介面的符號引用;
        如果在class_index發現有名稱和描述匹配的方法,則查找成功,直接返回引用,否則就會在其父類介面中遞歸查找,如果還是找不到或者找到的是類,就直接拋異常。

⑸ 如何設置JVM參數

設置eclipse jvm參數

打開Eclipse 或者 MyEclipse

打開 Windows -> Preferences -> Java -> Installed JREs

在 Default VM Arguments輸入框內輸入: -Xms512m -Xmx512m

解釋:

-Xms是設置java虛擬機的最小分配內存;-Xmx則是最大分配內存;512m為內存空間

一般-Xmx設置為你電腦物理內存的1/4,而把-Xms和 -Xmx設置為一樣,

其實你可以設置得更大一些,只要系統能分配足夠的內存就可以了,如果設置過大系統會提示你的。

⑹ JVM是如何工作的呢

Java虛擬機
一、什麼是Java虛擬機

Java虛擬機是一個想像中的機器,在實際的計算機上通過軟體模擬來實現。Java虛擬機有自己想像中的硬體,如處理器、堆棧、寄存器等,還具有相應的指令系統。

1.為什麼要使用Java虛擬機

Java語言的一個非常重要的特點就是與平台的無關性。而使用Java虛擬機是實現這一特點的關鍵。一般的高級語言如果要在不同的平台上運行,至少需要編譯成不同的目標代碼。而引入Java語言虛擬機後,Java語言在不同平台上運行時不需要重新編譯。Java語言使用模式Java虛擬機屏蔽了與具體平台相關的信息,使得Java語言編譯程序只需生成在Java虛擬機上運行的目標代碼(位元組碼),就可以在多種平台上不加修改地運行。Java虛擬機在執行位元組碼時,把位元組碼解釋成具體平台上的機器指令執行。

2.誰需要了解Java虛擬機

Java虛擬機是Java語言底層實現的基礎,對Java語言感興趣的人都應對Java虛擬機有個大概的了解。這有助於理解Java語言的一些性質,也有助於使用Java語言。對於要在特定平台上實現Java虛擬機的軟體人員,Java語言的編譯器作者以及要用硬體晶元實現Java虛擬機的人來說,則必須深刻理解Java虛擬機的規范。另外,如果你想擴展Java語言,或是把其它語言編譯成Java語言的位元組碼,你也需要深入地了解Java虛擬機。

3.Java虛擬機支持的數據類型

Java虛擬機支持Java語言的基本數據類型如下:

byte://1位元組有符號整數的補碼
short://2位元組有符號整數的補碼
int://4位元組有符號整數的補碼
long://8位元組有符號整數的補碼
float://4位元組IEEE754單精度浮點數
double://8位元組IEEE754雙精度浮點數
char://2位元組無符號Unicode字元

幾乎所有的Java類型檢查都是在編譯時完成的。上面列出的原始數據類型的數據在Java執行時不需要用硬體標記。*作這些原始數據類型數據的位元組碼(指令)本身就已經指出了*作數的數據類型,例如iadd、ladd、fadd和dadd指令都是把兩個數相加,其*作數類型別是int、long、 float和double。虛擬機沒有給boolean(布爾)類型設置單獨的指令。boolean型的數據是由integer指令,包括integer 返回來處理的。boolean型的數組則是用byte數組來處理的。虛擬機使用IEEE754格式的浮點數。不支持IEEE格式的較舊的計算機,在運行 Java數值計算程序時,可能會非常慢。

虛擬機支持的其它數據類型包括:
object//對一個Javaobject(對象)的4位元組引用
returnAddress//4位元組,用於jsr/ret/jsr-w/ret-w指令
注:Java數組被當作object處理。

虛擬機的規范對於object內部的結構沒有任何特殊的要求。在Sun公司的實現中,對object的引用是一個句柄,其中包含一對指針:一個指針指向該object的方法表,另一個指向該object的數據。用Java虛擬機的位元組碼表示的程序應該遵守類型規定。Java虛擬機的實現應拒絕執行違反了類型規定的位元組碼程序。Java虛擬機由於位元組碼定義的限制似乎只能運行於32位地址空間的機器上。但是可以創建一個Java虛擬機,它自動地把位元組碼轉換成64位的形式。從Java虛擬機支持的數據類型可以看出,Java對數據類型的內部格式進行了嚴格規定,這樣使得各種Java虛擬機的實現對數據的解釋是相同的,從而保證了Java的與平台無關性和可
移植性。

二、Java虛擬機體系結構

Java虛擬機由五個部分組成:一組指令集、一組寄存器、一個棧、一個無用單元收集堆(Garbage-collected-heap)、一個方法區域。這五部分是Java虛擬機的邏輯成份,不依賴任何實現技術或組織方式,但它們的功能必須在真實機器上以某種方式實現。

1.Java指令集

Java虛擬機支持大約248個位元組碼。每個位元組碼執行一種基本的CPU運算,例如,把一個整數加到寄存器,子程序轉移等。Java指令集相當於Java程序的匯編語言。
Java指令集中的指令包含一個單位元組的*作符,用於指定要執行的*作,還有0個或多個*作數,提供*作所需的參數或數據。許多指令沒有*作數,僅由一個單位元組的*作符構成。 虛擬機的內層循環的執行過程如下:

do{
取一個*作符位元組;
根據*作符的值執行一個動作;
}while(程序未結束)

由於指令系統的簡單性,使得虛擬機執行的過程十分簡單,從而有利於提高執行的效率。指令中*作數的數量和大小是由*作符決定的。如果*作數比一個位元組大,那麼它存儲的順序是高位位元組優先。例如,一個16位的參數存放時佔用兩個位元組,其值為:

第一個位元組*256+第二個位元組位元組碼指令流一般只是位元組對齊的。指令tableswitch和lookup是例外,在這兩條指令內部要求強制的4位元組邊界對齊。

2.寄存器

Java虛擬機的寄存器用於保存機器的運行狀態,與微處理器中的某些專用寄存器類似。

Java虛擬機的寄存器有四種:
pc:Java程序計數器。
optop:指向*作數棧頂端的指針。
frame:指向當前執行方法的執行環境的指針。
vars:指向當前執行方法的局部變數區第一個變數的指針。

Java虛擬機

Java虛擬機是棧式的,它不定義或使用寄存器來傳遞或接受參數,其目的是為了保證指令集的簡潔性和實現時的高效性(特別是對於寄存器數目不多的處理器)。
所有寄存器都是32位的。

3.棧

Java虛擬機的棧有三個區域:局部變數區、運行環境區、*作數區。

(1)局部變數區 每個Java方法使用一個固定大小的局部變數集。它們按照與vars寄存器的字偏移量來定址。局部變數都是32位的。長整數和雙精度浮點數占據了兩個局部變數的空間,卻按照第一個局部變數的索引來定址。(例如,一個具有索引n的局部變數,如果是一個雙精度浮點數,那麼它實際占據了索引n和n+1所代表的存儲空間。)虛擬機規范並不要求在局部變數中的64位的值是64位對齊的。虛擬機提供了把局部變數中的值裝載到*作數棧的指令, 也提供了把*作數棧中的值寫入局部變數的指令。

(2)運行環境區 在運行環境中包含的信息用於動態鏈接,正常的方法返回以及異常傳播。

·動態鏈接
運行環境包括對指向當前類和當前方法的解釋器符號表的指針,用於支持方法代碼的動態鏈接。方法的class文件代碼在引用要調用的方法和要訪問的變數時使用符號。動態鏈接把符號形式的方法調用翻譯成實際方法調用,裝載必要的類以解釋還沒有定義的符號,並把變數訪問翻譯成與這些變數運行時的存儲結構相應的偏移地址。動態鏈接方法和變數使得方法中使用的其它類的變化不會影響到本程序的代碼。

·正常的方法返回
如果當前方法正常地結束了,在執行了一條具有正確類型的返回指令時,調用的方法會得到一個返回值。執行環境在正常返回的情況下用於恢復調用者的寄存器,並把調用者的程序計數器增加一個恰當的數值,以跳過已執行過的方法調用指令,然後在調用者的執行環境中繼續執行下去。

·異常和錯誤傳播
異常情況在Java中被稱作Error(錯誤)或Exception(異常),是Throwable類的子類,在程序中的原因是:①動態鏈接錯,如無法找到所需的class文件。②運行時錯,如對一個空指針的引用

·程序使用了throw語句。
當異常發生時,Java虛擬機採取如下措施:
·檢查與當前方法相聯系的catch子句表。每個catch子句包含其有效指令范圍,能夠處理的異常類型,以及處理異常的代碼塊地址。
·與異常相匹配的catch子句應該符合下面的條件:造成異常的指令在其指令范圍之內,發生的異常類型是其能處理的異常類型的子類型。如果找到了匹配的catch子句,那麼系統轉移到指定的異常處理塊處執行;如果沒有找到異常處理塊,重復尋找匹配的catch子句的過程,直到當前方法的所有嵌套的 catch子句都被檢查過。
·由於虛擬機從第一個匹配的catch子句處繼續執行,所以catch子句表中的順序是很重要的。因為Java代碼是結構化的,因此總可以把某個方法的所有的異常處理器都按序排列到一個表中,對任意可能的程序計數器的值,都可以用線性的順序找到合適的異常處理塊,以處理在該程序計數器值下發生的異常情況。
·如果找不到匹配的catch子句,那麼當前方法得到一個"未截獲異常"的結果並返回到當前方法的調用者,好像異常剛剛在其調用者中發生一樣。如果在調用者中仍然沒有找到相應的異常處理塊,那麼這種錯誤傳播將被繼續下去。如果錯誤被傳播到最頂層,那麼系統將調用一個預設的異常處理塊。
(3)*作數棧區 機器指令只從*作數棧中取*作數,對它們進行*作,並把結果返回到棧中。選擇棧結構的原因是:在只有少量寄存器或非通用寄存器的機器(如Intel486)上,也能夠高效地模擬虛擬機的行為。*作數棧是32位的。它用於給方法傳遞參數,並從方法接收結果,也用於支持*作的參數,並保存*作的結果。例如,iadd指令將兩個整數相加。相加的兩個整數應該是*作數棧頂的兩個字。這兩個字是由先前的指令壓進堆棧的。這兩個整數將從堆棧彈出、相加,並把結果壓回到*作數棧中。

每個原始數據類型都有專門的指令對它們進行必須的*作。每個*作數在棧中需要一個存儲位置,除了long和double型,它們需要兩個位置。* 作數只能被適用於其類型的*作符所*作。例如,壓入兩個int類型的數,如果把它們當作是一個long類型的數則是非法的。在Sun的虛擬機實現中,這個限制由位元組碼驗證器強制實行。但是,有少數*作(*作符pe和swap),用於對運行時數據區進行*作時是不考慮類型的。

4.無用單元收集堆

Java的堆是一個運行時數據區,類的實例(對象)從中分配空間。Java語言具有無用單元收集能力:它不給程序員顯式釋放對象的能力。Java不規定具體使用的無用單元收集演算法,可以根據系統的需求使用各種各樣的演算法。

5.方法區

方法區與傳統語言中的編譯後代碼或是Unix進程中的正文段類似。它保存方法代碼(編譯後的java代碼)和符號表。在當前的Java實現中,方法代碼不包括在無用單元收集堆中,但計劃在將來的版本中實現。每個類文件包含了一個Java類或一個Java界面的編譯後的代碼。可以說類文件是Java 語言的執行代碼文件。為了保證類文件的平台無關性,Java虛擬機規范中對類文件的格式也作了詳細的說明。其具體細節請參考Sun公司的Java虛擬機規范。

內容來源於網上。

⑺ JVM性能調優指南(一)

-help
-server -client
-version -showversion
-cp -classpath

調整為 完全解釋執行 編譯模式:

調整為 編譯執行 編譯模式:

最後歷友一行的 mixed mode 表明JVM默認使用的編譯模式是 混合模式

使用最多的空爛褲一種參數類型

格式: -XX:[+/-] <name> 表示啟用或者禁用name屬性
比如:
-XX:+UseConcMarkSweepGC 表示啟用CMS垃圾回收器
-XX:+UseG1GC 表示啟用G1垃圾回收器

格式: -XX:<name> = <value> 表示name屬性的值為value
比如:
-XX:MaxGCPauseMillis=500 表示GC最大停頓時間是500毫秒
-XX:GCTimeRatio=19 表示...

雖然1以X開頭,但是不是X類型參數,而是XX類型的參數

如查看JVM版本信息: java -XX:+PrintFlagsFinal -version > ~/version.txt

註: = 表示默認值, =: 表示修改後的值

關於jps等命令的詳解,可參考此文檔 https://docs.oracle.com/javase/8/docs/technotes/tools/unix/index.html

如查看一個java進程id為9723的tomcat服務最大堆內存大小

查看一個進程的所有運行時參數:

Non-default VM flags 表示手動賦值過的參數,其中有些是tomcat設置的
Command line :與 Non-default VM flags

查看垃圾回收器信息

格式: jstat -class 進程id 每隔多少毫秒 一共輸出多少次
如:查看斗簡一個進程id為29159的java進程,每隔1s輸出,一共輸出10次

要查看一個java進程的垃圾收集器信息,可使用 jstat -gc 進程id 每隔多少毫秒 一共輸出多少次

S0C : Current survivor space 0 capacity (kB). 表示survivor 0區的總大小
S1C : Current survivor space 1 capacity (kB). 表示survivor 1區的總大小
S0U : Survivor space 0 utilization (kB). 表示survivor 0區使用了的大小
S1U : Survivor space 1 utilization (kB). 表示survivor 1區使用了的大小
EC : Current eden space capacity (kB). 表示eden區總大小
EU : Eden space utilization (kB). 表示eden區使用了的大小
OC : Current old space capacity (kB). 表示old區總大小
OU : Old space utilization (kB). 表示old區使用了的大小
MC : Metaspace capacity (kB). 表示Metaspace區總大小
MU : Metacspace utilization (kB). 表示Metaspace區使用了的大小
CCSC : Compressed class space capacity (kB). 表示壓縮類空間總量
CCSU : Compressed class space used (kB). 表示壓縮類空間使用量
YGC : Number of young generation garbage collection events. 表示Young GC的次數
YGCT : Young generation garbage collection time. 表示Young GC的時間
FGC : Number of full GC events. 表示full GC的次數
FGCT : Full garbage collection time. 表示full GC的時間
GCT : Total garbage collection time. 表示總的 GC的時間

模擬內存溢出:

設置啟動參數:

啟動application,發現出現內存溢出

-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=./

格式: jmap -mp:format=b,file=路徑/heap.hprof 進程id
其他命令: jmap -heap 進程id 查看堆信息

右鍵查看com.imooc.monitor_tuning.chapter2.User的強引用

也可以查看對象樹:

格式: jstack 進程id

訪問/loop端點三次,然後使用top命令:

然後在導出的7930.txt文件中找到2037

訪問/loop端點,製造死循環,使用jstack命令導出線程堆棧信息:

最後一行已提示:Found 1 deadlock

相關資料:
jdk8工具集
https://docs.oracle.com/javase/8/docs/technotes/tools/unix/index.html
Troubleshooting
https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/
jps
https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jps.html
jinfo
https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jinfo.html
jstat
https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jstat.html
jmap:
https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jmap.html
mat:
http://www.eclipse.org/mat/downloads.php
jstack:
https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jstack.html
java線程的狀態
https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/tooldescr034.html
java線程狀態轉化:
https://mp.weixin.qq.com/s/GsxeFM7QWuR--Kbpb7At2w
死循環導致CPU負載高
https://blog.csdn.net/goldenfish1919/article/details/8755378
正則表達式導致死循環:
https://blog.csdn.net/goldenfish1919/article/details/49123787

⑻ 「JVM」調優參數總結

因此我們一般設罩滑置-Xms、-Xmx這兩個參數相等,可以避螞悶豎免在每次GC 後動態調整堆的大小帶來的影響。

吞吐量和停頓時間是互斥的。 對於後端服務(比如後台計算任務),吞吐量優先考慮(並行垃圾回收);

對於前端應用,RT響應悶大時間優先考慮,減少垃圾收集時的停頓時間,適用場景是Web系統(並發垃圾回收)