elasticsearch,garbage-collection,jvm,heap,Java,elasticsearch,Garbage Collection,Jvm,Heap" /> elasticsearch,garbage-collection,jvm,heap,Java,elasticsearch,Garbage Collection,Jvm,Heap" />

如何确定Java堆是否使用压缩指针,以及是否驻留在内存中的地址0处?

如何确定Java堆是否使用压缩指针,以及是否驻留在内存中的地址0处?,java,elasticsearch,garbage-collection,jvm,heap,Java,elasticsearch,Garbage Collection,Jvm,Heap,我试图跟进本博客中的一些技巧,其中讨论了调整Java堆大小的好处,以便(a)可以使用压缩指针(对于32GB以下的堆)和(b)使堆驻留在内存中的地址0处。本文详细介绍了压缩指针如何更有效地利用堆空间,并解释了当堆位于地址0时,这会减少解析指针地址所需的算术量。最后,文章说,如果我使用JVM选项-XX:+UnlockDiagnosticVMOptions-XX:+PrintCompressedOopsMode,我将看到如下日志输出: 堆地址:0x000000011be00000,大小:27648MB

我试图跟进本博客中的一些技巧,其中讨论了调整Java堆大小的好处,以便(a)可以使用压缩指针(对于32GB以下的堆)和(b)使堆驻留在内存中的地址0处。本文详细介绍了压缩指针如何更有效地利用堆空间,并解释了当堆位于地址0时,这会减少解析指针地址所需的算术量。最后,文章说,如果我使用JVM选项
-XX:+UnlockDiagnosticVMOptions
-
XX:+PrintCompressedOopsMode
,我将看到如下日志输出:

堆地址:0x000000011be00000,大小:27648MB,基于零的压缩Oops

这表示启用了基于零的压缩OOP,或输出如下

堆地址:0x00000001184000000,大小:28672MB,压缩的Oops,基数:0x00000001183ff000

这表明堆从零以外的地址开始,因此需要前面提到的增加算术处理量

然而,当我尝试这些选项并浏览我的应用程序(弹性搜索)的日志目录时,我找不到这样的消息。如果有人能建议我如何强制记录基于零(或非基于零)的压缩指针的详细信息,我将非常感激

决议:

很好的答案!。。我接受了@apangin,并将他提供的java程序包装在一个shell脚本中,只要你有java,这个脚本就可以运行。。如果您正在查看Java堆,那么您应该这样做!下面是脚本:

可以在运行的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);
    }
}
在JDK9之前,这需要在类路径中包含
${JDK_HOME}/lib/sa jdi.jar
。该程序需要在与运行目标进程相同的JVM版本下运行

然而,当我尝试这些选项并浏览我的应用程序(弹性搜索)的日志目录时,我找不到这样的消息


可能是因为它只将应用程序消息记录到该目录。您还需要将JVM输出记录到一个文件中,或者检查stdout或stderr以获取这些消息。

假设您使用的是5.x及更高版本的Linux和ES

在整个集群中收集信息的最有效方法是使用:

curl-XGET “*.jvm。使用\u压缩\u普通\u对象\u指针”

{“nodes”:{“-jYDCxbpT2SBKc4dTfOYsA”:{“jvm”:{“使用压缩的普通对象指针”:“true”}}}

相同的信息记录在主日志-/var/log/elasticsearch/elasticsearch.log中

[2017-10-06T23:03:15223][INFO][o.e.e.NodeEnvironment][jYDCxb] 堆大小[1.9gb],压缩的普通对象指针[true]

如果您对真正的JVM输出感兴趣,那么您必须知道,默认情况下JVM将其消息写入标准输出,并且在Linux发行版上,此输出默认配置为重定向到journalctl。所以你有两个选择。第一个是阅读《华尔街日报》:

sudo journalctl-u elasticsearch.service

窄klass基:0x000000000000000,窄klass移位:3 压缩类空间大小:1073741824地址:0x0000000100000000请求地址:0x0000000100000000

但有时journalctl在默认情况下被禁用,您必须通过从ES命令行参数中删除
--quite
参数,在守护程序配置
/usr/lib/systemd/system/elasticsearch.service
中更改此设置。第二种方法是最简单的跨平台重定向JVM消息到特定的GC日志输出:

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


现在您可以在
/tmp/vm.log

中看到所有与GC相关的输出。请注意,在这两种情况下,堆都不是从零开始的。但在第一种情况下,起始地址和堆大小之和低于32GiB阈值,这允许基于零的寻址。但是为什么这个问题被标记为“垃圾收集”?如果我的回答对你没有帮助,请提供关于你的操作系统和ES版本的信息。哇。。答案很好。明天我将回顾并尝试这些建议。作为对@Holger的回应-标记垃圾收集的原因是,除了其他与垃圾收集相关的调整外,我们正在尝试优化堆大小的设置。。我认为这个主题与任何其他人都相关/thnx