我获取了 JVM 的 jmap -permstat
输出(报告为版本 24.76-b04),它报告了以下总计:
total = 5190 76930 1031431696 N/A alive=1, dead=5189 N/A
这应该是条目的数量、使用此信息的类、用于元数据和 Activity 信息的字节数。
现在,我想知道为什么它会报告 1031431696 字节
,当我使用 -XX:MaxPermSize=256m
启动我的 VM 时,只差 1 GB。有人可以阐明这个数字是如何计算的吗?
不知道它是否相关,但这是使用 Rhino,其中约 3k 个条目是 DefiningClassLoader
。
最佳答案
我稍微看了看jmap -permstat
实现的代码。使用的字节数是基于类加载器加载的不同类型数据(方法、字段、接口(interface)等)的大小的估计值。
为加载类计算大小的顶级方法是 sun.jvm.hotspot.tools.PermStat.computeSize
:
private long computeSize(InstanceKlass k) {
long size = 0L;
// the InstanceKlass object itself
size += k.getObjectSize();
// Constant pool
ConstantPool cp = k.getConstants();
size += cp.getObjectSize();
size += objectSize(cp.getCache());
size += objectSize(cp.getTags());
// Interfaces
size += arraySize(k.getLocalInterfaces());
size += arraySize(k.getTransitiveInterfaces());
// Inner classes
size += objectSize(k.getInnerClasses());
// Fields
size += objectSize(k.getFields());
// Methods
ObjArray methods = k.getMethods();
int nmethods = (int) methods.getLength();
if (nmethods != 0L) {
size += methods.getObjectSize();
for (int i = 0; i < nmethods; ++i) {
Method m = (Method) methods.getObjAt(i);
size += m.getObjectSize();
size += objectSize(m.getConstMethod());
}
}
// MethodOrdering - an int array that records the original
// ordering of methods in the class file
size += arraySize(k.getMethodOrdering());
return size;
}
我的猜测是,在您的案例中,这种估计非常失败。如果不详细检查您的 JVM 版本的对象大小计算并结合您的应用程序中加载的类的特征,很难说它失败的原因。
另外,Troubleshooting Guide for Java SE 6 with HotSpot VM提到该值是一个近似值。
归根结底,对字节使用值持保留态度。
关于java - 为什么 jmap -permstat 会报告超过使用的 MaxPermSize 字节数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29875902/