class AAA {
static {
System.out.println("class AAA static block println"); // 并没有打印此句
}
}
public class Main {
public static void main(String[] args) {
System.out.println("hello world!");
}
}
一直以来都以为 static 标识的代码块或者是字段,都是在类加载的时候就被执行或者赋值了,但是这么一看....感觉自己的世界观都要被刷新了。
所以此处是类没有被加载吗?还是说我们一直以来认为的,静态代码块、字段都在类加载的时候被初始化的,这个观点是错误的?
在《深入理解Java虚拟机:JVM高级特性与最佳实践 第2版》中找到一些线索,如下图:
所以,照这么说,是在第一次主动访问该类的时候执行?小弟好生迷惑啊....大家快说说你们的观点
클래스 초기화 및 객체 초기화.
static에 포함된 코드 블록과 변수는 클래스가 초기화될 때만 실행되며, 초기화를 위한 5가지 조건도 알고 있습니다.
명확하게 설명해 주세요.
우선 동일한 .java 파일에 넣어도 컴파일 후에도 여전히 두 개의 다른 클래스 파일입니다. 믿을 수 없다면 해당 하위에 생성된 .class 파일을 살펴보세요. 빈 패키지.
둘째, 클래스가 초기화되면 클래스의 정적 변수가 초기화되고 정적 코드 블록이 실행됩니다. 따라서 가상머신은 new, getstatic, putstatic 명령어의 사용, 메인 함수가 위치한 클래스, 리플렉션, 상위 클래스 등 5가지 초기화 조건을 규정한다. 그러나 이러한 다섯 가지 상황을 제외하고는 클래스 초기화가 트리거될 수 없습니다. 코드에 표시된 것처럼 Main.class에는 호출이나 상위-하위 관계 또는 AAA.class에 대한 반영이 없습니다. 따라서 AAA.class는 당연히 초기화되지 않습니다.
Java 클래스 로딩 과정에 대한 다른 블로그를 읽어보실 수 있습니다
이해하셨나요?
-XX:+TraceClassLoading
이것을 추가하면 AAA가 로드되지 않은 것을 확인할 수 있습니다
여기서 다루어야 할 두 가지 개념이 있습니다.
클래스 로딩 메커니즘
Java, 컴파일러, 바이트코드, JVM 사양 및 구현.
클래스 로딩은 클래스 로더(Classloader)를 통해 완료됩니다. 구체적인 로딩 전략은 JVM의 구체적인 구현에 따라 다릅니다. 일반적으로 두 가지 유형으로 나눌 수 있습니다.
다른 클래스에서 참조하는 한 로딩이 필요합니다.
지연 로딩, 클래스에 액세스할 때 로딩.
Java, 컴파일러, 바이트코드 및 JVM에는 고유한 사양이 있으며 사양을 통해 함께 작동합니다.
컴파일 버튼은 Java 코드를 표준화된 바이트코드 파일로 컴파일합니다. 각 클래스(외부 클래스, 내부 클래스, 익명 클래스)는 별도의 바이트코드 파일(클래스 파일)로 컴파일되며 이때 JVM은 클래스를 로드합니다. , 이러한 클래스 파일에서 하나씩 로드됩니다.
이제 코드로 돌아갑니다.
Java 계층에서는 AAA와 Main 두 클래스를 하나의 파일에 넣습니다. 컴파일 후 컴파일러는 AAA.class와 Main.class라는 두 개의 클래스 파일을 생성합니다.
두 클래스는 코드 구성 측면에서 함께 있지만 컴파일 후에는 독립적이며 Main은 AAA를 참조하지 않으므로 어떤 클래스 로딩 방법을 사용하더라도 클래스 AAA 로딩을 트리거하지 않습니다. AAA의 정적 코드 블록은 실행되지 않습니다.
답변해주신 위 열정적인 네티즌분들께 진심으로 감사드립니다!
확인
AAA 클래스는 실제로 로드되지 않고 Main 클래스만 로드됩니다. (질문의 스크린샷: 네 번째 초기화 조건, 메인 클래스는 jvm에 의해 자동으로 로드됩니다.)
으아악결론
클래스의 정적 필드 | 코드 블록은 클래스가 로드될 때 실제로 초기화되거나 실행됩니다!
확장명령이 실행되는 한 클래스가 jvm에 의해 로드될 것이라고 생각했습니다. 실제로는 그렇지 않습니다. 명령은
javac
파일을 jvm이 이해할 수 있는.java
파일로만 변환합니다..class
그럼 클래스가 jvm에 의해 로드되었는지 어떻게 알 수 있나요? "Java Virtual Machine에 대한 심층적인 이해: JVM 고급 기능 및 모범 사례 2판"과 네티즌들의 열광적인 답변에 따르면 언제 로드될지 명확한 시기가 정해지지 않았습니다!
하지만! jvm에서는 클래스가 초기화되는 시점을 명확하게 규정하고 있습니다 - 위 스크린샷에는 4가지 타입이 있습니다! 클래스 로딩은 클래스 초기화보다 우선하므로 여기서는 일시적으로 이러한 상황이 클래스 로딩을 트리거하는 조건이라고 생각할 수 있습니다.
오빠가 무식해서 부적절한 내용을 요약했네요 정정해주세요! 감사합니다Main.java와 AAA.java를 같은 폴더에 넣으세요.
메인 함수에
를 작성하세요. 으아악실행
메인 메서드가 실행되면 Main 클래스만 로드됩니다. Main 클래스에서는 AAA 클래스가 사용되지 않으며 AAA 클래스는 로드되지 않습니다. 동일한 파일을 사용하면 동시에 로드됩니다.
AAA 클래스는 다른 곳에서는 새로운 것이 아니며 그에 따라 정적 필드를 가져오거나 설정하지도 않고 정적 메서드를 호출하지도 않습니다.
그래서 자동으로 초기화되지 않습니다.
은 두 개의 클래스에 배치됩니다. 공개로 선언된 클래스의 기본 클래스는 초기화는커녕 사용되지도 않고 로드되지도 않습니다.