我对类加载的理解是,一个类在第一次需要时被加载(以非常简单的方式)。运行与-verbose下面的示例:类和打印时,其clinit叫我观察到的东西,我真的不能解释,虽然消息的迭代器类的修改版本:加载,链接和初始化 - 何时加载类?
public class IteratorsTest
{
public static void main(String[] args)
{
com.google.common.collect.Iterators.forArray(1, 2, 3);
}
}
的(清理后)输出如下:
[Loaded com.google.common.collect.Iterators from file:...]
[Loaded com.google.common.collect.Iterators$1 from file:...]
---------> Iterators <clinit>
为什么在调用clinit之前加载了Iterator $ 1?它只在clinit中定义,不是吗?
static final UnmodifiableListIterator<Object> EMPTY_LIST_ITERATOR =
new UnmodifiableListIterator<Object>() {
...
}
导致在随后的字节码:
static <clinit>()V
L0
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
LDC "---------> Iterators clinit --------------"**
INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
L1
NEW com/google/common/collect/Iterators$1
DUP
INVOKESPECIAL com/google/common/collect/Iterators$1.<init>()V
L2
PUTSTATIC com/google/common/collect/Iterators.EMPTY_LIST_ITERATOR : Lcom/google/common/collect/UnmodifiableListIterator;
而迷惑我更我多了一个样本(太复杂,张贴在这里),其中相同的代码行作为主以上导致以下输出:
[Loaded com.google.common.collect.Iterators from file:...]
---------> Iterators <clinit>
[Loaded com.google.common.collect.Iterators$1 from file:...]
这实际上是我从简单的测试程序以及所期望的。
我试图在这里找到答案https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-5.html,但这并没有真正的帮助。
- 什么可能是有时clinit首先被执行,有时首先被加载的匿名类的原因是什么?
- 有没有办法跟踪JVM何时调用类的clinit?类似于-verbose:class或-XX:+ TraceClassLoading等等?
openjdk9的新日志记录基础结构允许对很多内部进行相当细致的分解,包括类加载和初始化。也许这会提供你想要的信息。 – the8472
好主意,我读了关于新的日志功能,但还没有尝试过。也许值得做一个测试运行。谢谢! –
尽管我发现它,但我想知道JDK9是否会有所帮助,而且事实上,这可以完成这项工作。我开始使用-Xlog:class + init = info,class + load = info:file = trace.log(btw:是否有可用选择器的完整列表?http://openjdk.java.net/ jeps/158是不够的)。 PS:它实际上是你在这里的评论http://stackoverflow.com/questions/39321345/how-do-i-measure-jvm-startup-time我在这里读到第一。 –