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

Chr*_*ord 5 java garbage-collection jvm heap-memory elasticsearch

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

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

这表明启用了从零开始的压缩oops,或者像这样输出

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

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

但是,当我尝试这些选项并通过我的应用程序(弹性搜索)日志目录进行 grep 查找时,我找不到此类消息。如果有人可以建议我如何强制记录从零开始(或非从零开始)的压缩指针的详细信息,我将非常感激。

解决:

很好的答案!..我接受了@apangin的,并将他提供的java程序包装在一个shell脚本中,只要你有java就可以运行..如果你正在查看Java堆,你应该这样做!这是脚本: https: //github.com/buildlackey/scripts/blob/master/verify_compressed_pointers_from_zero_offset.sh

Iva*_*tov 5

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

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

卷曲-XGET“ http://localhost:9200/_nodes/jvm?filter_path=nodes .*.jvm.using_compressed_ordinary_object_pointers”

{“节点”:{“-jYDCxbpT2SBKc4dTfOYsA”:{“jvm”:{“using_compressed_ordinary_object_pointers”:“true”}}}}

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

[2017-10-06T23:03:15,223][INFO][oeeNodeEnvironment][-jYDCxb]堆大小[1.9gb],压缩普通对象指针[true]

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

sudojournalctl-uelasticsearch.service

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

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

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

现在您可以在中看到所有 GC 相关的输出/tmp/vm.log


apa*_*gin 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

在 JDK 9 之前,这需要包含${JDK_HOME}/lib/sa-jdi.jar在类路径中。该程序需要在与运行目标进程相同的 JVM 版本下运行。