2017-10-06 163 views
3

我想跟進這篇博客中的一些技巧https://www.elastic.co/blog/a-heap-of-trouble#ref5,它討論了調整一個Java堆的好處,以便(a)可以使用壓縮指針(對於32GB以下的堆)和(b)以便堆駐留在地址0在內存中。本文詳細介紹了壓縮指針如何更有效地利用堆空間,並解釋了當堆存放在地址0時,這減少了解析指針地址所需的算術量。最後,文章說,如果我使用JVM選項-XX:+UnlockDiagnosticVMOptions - XX:+PrintCompressedOopsMode我會看到日誌輸出要麼是這樣的:如何確定Java堆是否使用壓縮指針以及是否駐留在內存中的地址0?

heap address: 0x000000011be00000, size: 27648 MB, zero based Compressed Oops

這表明從零開始壓縮哎呀啓用,或輸出這樣

heap address: 0x0000000118400000, size: 28672 MB, Compressed Oops with base: 0x00000001183ff000

這表明堆開始於非零的地址,因此需要前述的算術處理增加量。

但是,當我嘗試這些選項並通過我的應用程序(Elastic Search)日誌目錄grep'd時,我找不到這樣的消息。如果任何人都可以告訴我如何強制記錄零基(或不是零)的壓縮指針的細節,我將非常感激。

解決方案:

偉大的答案。我接受了@ apangin的,我裹着他在shell腳本提供的Java程序,只要你有java的..可以運行,你應該如果你正在尋找Java堆!這裏是腳本:https://github.com/buildlackey/scripts/blob/master/verify_compressed_pointers_from_zero_offset.sh

+0

請注意,在這兩種情況下,堆不會從零開始。但在第一種情況下,起始地址和堆大小的總和低於32GiB閾值,這允許基於零的尋址。但爲什麼這個問題標籤爲「垃圾收集」? – Holger

+0

如果我的回答沒有幫助你,請提供有關您的操作系統和ES版本的信息。 – Ivan

+0

哇..很好的答案。我將在明天審查並嘗試這些建議。作爲對@Holger的迴應,標記垃圾收集的原因是因爲我們試圖優化堆大小的設置以及其他垃圾收集相關的調整..認爲這個話題與任何其他調整GC相關。 /日Thnx –

回答

3

HotSpot Serviceability Agent即使不需要額外的命令行標誌,也可以在正在運行的JVM進程上顯示它。

以目標Java進程ID作爲參數運行以下程序。

import sun.jvm.hotspot.runtime.VM; 
import sun.jvm.hotspot.tools.Tool; 

public class CompressedOopsInfo extends Tool { 

    @Override 
    public void run() { 
     VM vm = VM.getVM(); 
     System.out.println("CompressedOops = " + vm.isCompressedOopsEnabled()); 
     System.out.println("CompressedClassPointers = " + vm.isCompressedKlassPointersEnabled()); 
     System.out.println("OOP base = 0x" + Long.toHexString(vm.getDebugger().getNarrowOopBase())); 
     System.out.println("OOP shift = " + vm.getDebugger().getNarrowOopShift()); 
    } 

    public static void main(String[] args) { 
     new CompressedOopsInfo().execute(args); 
    } 
} 

在JDK 9之前,這需要在類路徑中包含${JDK_HOME}/lib/sa-jdi.jar。程序需要在與運行目標進程相同的JVM版本下運行。

1

但是,當我嘗試這些選項並通過我的應用程序的(Elastic Search)日誌目錄grep'd時,我找不到這樣的消息。

可能是因爲它只記錄應用程序消息到該目錄。您還需要將JVM輸出記錄到文件中,或者檢查標準輸出或標準錯誤消息。

1

假設您正在使用版本爲5.x及更高版本的Linux和ES。

的最有效的方法來收集整個集羣的信息是使用the nodes info API

捲曲-XGET 「http://localhost:9200/_nodes/jvm?filter_path=nodes * JVM。using_compressed_ordinary_object_pointers」

{ 「節點」:{ 「 - jYDCxbpT2SBKc4dTfOYsA」:{ 「JVM」:{ 「using_compressed_ordinary_object_pointers」: 「真正的」}}}}

相同的信息被記錄到主日誌 - /var/log/elasticsearch/elasticsearch.log

[2017-10-06T23:03:15223] [INFO] [oeeNodeEnvironment] [-jYDCxb] 堆大小[1.9GB],壓縮普通對象指針[true]

如果您對真正的JVM輸出感興趣,那麼您必須知道,默認情況下,JVM會將其消息寫入標準輸出,並且在Linux發行版中,此輸出默認情況下會配置爲重定向到journalctl。所以你有兩個選擇。第一個是讀journalctl:

須藤journalctl -u elasticsearch.service

精細克拉斯基:0x0000000000000000,精細克拉斯移:3 壓縮類空間大小:1073741824地址:0x0000000100000000 REQ的地址: 0x0000000100000000

但有時journalctl默認是關閉的,你必須通過從ES命令行參數--quite參數來改變在守護程序配置/usr/lib/systemd/system/elasticsearch.service此設置。第二種方法是最簡單的和跨平臺 - 重定向JVM消息給特定的GC日誌輸出:

-XX:+ UnlockDiagnosticVMOptions -XX:+ PrintCompressedOopsMode -Xloggc:/tmp/vm.log

現在你可以看到所有的GC相關的輸出在/tmp/vm.log

相關問題