通过jol查看Java Object Layout时,发现一个奇怪现象。
public static void main(String[] args) throws Exception { out.println(VMSupport.vmDetails()); out.println(ClassLayout.parseClass(Throwable.class).toPrintable()); }
运行结果如下:
仔细点会发现,属性backtrace竟然不在此列
/** * Native code saves some indication of the stack backtrace in this slot. */ private transient Object backtrace;
按理说只有static的才不在此列。深入源码,没发现啥黑洞。
google,google,找到了问题的缘由。
https://bugs.openjdk.java.net/browse/JDK-4496456
https://bugs.openjdk.java.net/browse/JDK-8033735
https://bugs.openjdk.java.net/browse/JDK-8033735
将属性backtrace排除在外,是JDK有意为之的。
如果想解决,官方也提供了patch修复
diff -r c84312468f5c src/share/vm/prims/jvm.cpp --- a/src/share/vm/prims/jvm.cpp Fri Jan 24 13:06:52 2014 +0100 +++ b/src/share/vm/prims/jvm.cpp Wed Feb 05 17:43:53 2014 -0800 @@ -1790,9 +1790,6 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDecl // Ensure class is linked k->link_class(CHECK_NULL); - // 4496456 We need to filter out java.lang.Throwable.backtrace - bool skip_backtrace = false; - // Allocate result int num_fields; @@ -1803,11 +1800,6 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDecl } } else { num_fields = k->java_fields_count(); - - if (k() == SystemDictionary::Throwable_klass()) { - num_fields--; - skip_backtrace = true; - } } objArrayOop r = oopFactory::new_objArray(SystemDictionary::reflect_Field_klass(), num_fields, CHECK_NULL); @@ -1816,12 +1808,6 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDecl int out_idx = 0; fieldDescriptor fd; for (JavaFieldStream fs(k); !fs.done(); fs.next()) { - if (skip_backtrace) { - // 4496456 skip java.lang.Throwable.backtrace - int offset = fs.offset(); - if (offset == java_lang_Throwable::get_backtrace_offset()) continue; - } - if (!publicOnly || fs.access_flags().is_public()) { fd.reinitialize(k(), fs.index()); oop field = Reflection::new_field(&fd, UseNewReflection, CHECK_NULL);