Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/384.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java ThreadMXBean.getThreadAllocatedBytes(长id)中包含哪些JVM运行时数据区域_Java_Memory Management_Jvm - Fatal编程技术网

Java ThreadMXBean.getThreadAllocatedBytes(长id)中包含哪些JVM运行时数据区域

Java ThreadMXBean.getThreadAllocatedBytes(长id)中包含哪些JVM运行时数据区域,java,memory-management,jvm,Java,Memory Management,Jvm,我试图获得一些代码片段的内存消耗。经过一些搜索,我意识到可以使用ThreadMXBean.getThreadAllocatedBytes(长id)来实现这一点。因此,我使用以下代码测试了此方法: ThreadMXBean threadMXBean = (ThreadMXBean) ManagementFactory.getThreadMXBean(); long id = Thread.currentThread().getId(); // new Long(0);

我试图获得一些代码片段的内存消耗。经过一些搜索,我意识到可以使用
ThreadMXBean.getThreadAllocatedBytes(长id)
来实现这一点。因此,我使用以下代码测试了此方法:

    ThreadMXBean threadMXBean = (ThreadMXBean) ManagementFactory.getThreadMXBean();
    long id = Thread.currentThread().getId();
//      new Long(0);
    long beforeMemUsage = threadMXBean.getThreadAllocatedBytes(id);
    long afterMemUsage = 0;

    {
        // put the code you want to measure here
        for (int i = 0; i < 10; i++) {
            new Long(i);
        }
    }

    afterMemUsage = threadMXBean.getThreadAllocatedBytes(id);
    System.out.println(afterMemUsage - beforeMemUsage);
1和10、10和20以及20和30之间的区别很容易解释,因为长对象的大小是24字节。但是我被0和1之间的巨大差异弄糊涂了。 实际上,我猜这是由类加载引起的。因此,我取消了第三行代码的注释,结果如下:

0 Long: 48 bytes
1 Long: 456 bytes
10 Long:    672 bytes
20 Long:    912 bytes
30 Long:    1152 bytes
0 Long: 48 bytes
1 Long: 72 bytes
10 Long:    288 bytes
20 Long:    528 bytes
30 Long:    768 bytes
结果似乎证实了我的猜测。然而,在我看来,类结构的信息存储在方法区域,而不是堆内存的一部分。如的Javadoc所示,它返回堆内存中分配的内存总量。我错过什么了吗

测试的JVM版本为:

java version "1.8.0_131"
Java(TM) SE Runtime Environment (build 1.8.0_131-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)

谢谢

第一次调用
new Long(0)
会导致解析
new
字节码引用的常量池条目。在第一次解析
常量\u Class\u info
时,JVM加载引用的类-
java.lang.Long

是用Java实现的,它当然可以分配Java对象。例如,方法在
parallelLockMap
中创建一个新锁对象和一个新条目:

    protected Object getClassLoadingLock(String className) {
        Object lock = this;
        if (parallelLockMap != null) {
            Object newLock = new Object();
            lock = parallelLockMap.putIfAbsent(className, newLock);
            if (lock == null) {
                lock = newLock;
            }
        }
        return lock;
    }
另外,在系统字典中查找类名时,JVM会创建一个新的字符串对象

我曾经记录JVM在加载
java.lang.Long
类时所做的所有堆分配。以下是可点击的交互式火焰图:

该图包括13个样本——每个分配的对象一个样本。未显示分配对象的类型,但可以从上下文(堆栈跟踪)轻松猜测它

  • 绿色表示Java堆栈跟踪
  • 黄色表示VM堆栈跟踪
请注意,每个
java\u lang\u String::basic\u create()
(及类似内容)分配两个对象:java.lang.String的一个实例及其备份
char[]
数组

该图由以下测试程序生成:

import one.profiler.AsyncProfiler;

public class ProfileHeapAlloc {

    public static void main(String[] args) throws Exception {
        AsyncProfiler profiler = AsyncProfiler.getInstance();

        // Dry run to skip allocations caused by AsyncProfiler initialization
        profiler.start("_ZN13SharedRuntime19dtrace_object_allocEP7oopDesci", 0);
        profiler.stop();

        // Real profiling session
        profiler.start("_ZN13SharedRuntime19dtrace_object_allocEP7oopDesci", 0);

        new Long(0);

        profiler.stop();
        profiler.execute("file=alloc.svg");
    }
}
如何运行:

java -Djava.library.path=/path/to/async-profiler -XX:+DTraceAllocProbes ProfileHeapAlloc

这里的
\u ZN13SharedRuntime19dtrace\u object\u allocEP7oopDesci
是for
SharedRuntime::dtrace\u object\u alloc()
函数,每当启用
DTraceAllocProbes
标志时,JVM就会为每个堆分配调用该函数。

很好的解释!我在笔记本电脑上复制了火焰图。但我看不出有13个Java对象被分配。你能解释一下吗?谢谢此外,
\u ZN13SharedRuntime19dtrace\u对象\u allocEP7oopDesci
是什么意思?