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
是forSharedRuntime::dtrace\u object\u alloc()
函数,每当启用DTraceAllocProbes
标志时,JVM就会为每个堆分配调用该函数。很好的解释!我在笔记本电脑上复制了火焰图。但我看不出有13个Java对象被分配。你能解释一下吗?谢谢此外,\u ZN13SharedRuntime19dtrace\u对象\u allocEP7oopDesci
是什么意思?