찾다

 >  Q&A  >  본문

java - Static 标识的字段或者是代码块,真的是在类加载的时候初始化的吗?

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版》中找到一些线索,如下图:

所以,照这么说,是在第一次主动访问该类的时候执行?小弟好生迷惑啊....大家快说说你们的观点

PHPzPHPz2803일 전713

모든 응답(8)나는 대답할 것이다

  • ringa_lee

    ringa_lee2017-04-18 10:54:20

    클래스 초기화 및 객체 초기화.

    static에 포함된 코드 블록과 변수는 클래스가 초기화될 때만 실행되며, 초기화를 위한 5가지 조건도 알고 있습니다.

    명확하게 설명해 주세요.
    우선 동일한 .java 파일에 넣어도 컴파일 후에도 여전히 두 개의 다른 클래스 파일입니다. 믿을 수 없다면 해당 하위에 생성된 .class 파일을 살펴보세요. 빈 패키지.
    둘째, 클래스가 초기화되면 클래스의 정적 변수가 초기화되고 정적 코드 블록이 실행됩니다. 따라서 가상머신은 new, getstatic, putstatic 명령어의 사용, 메인 함수가 위치한 클래스, 리플렉션, 상위 클래스 등 5가지 초기화 조건을 규정한다. 그러나 이러한 다섯 가지 상황을 제외하고는 클래스 초기화가 트리거될 수 없습니다. 코드에 표시된 것처럼 Main.class에는 호출이나 상위-하위 관계 또는 AAA.class에 대한 반영이 없습니다. 따라서 AAA.class는 당연히 초기화되지 않습니다.

    Java 클래스 로딩 과정에 대한 다른 블로그를 읽어보실 수 있습니다

    이해하셨나요?

    회신하다
    0
  • 阿神

    阿神2017-04-18 10:54:20

    -XX:+TraceClassLoading
    이것을 추가하면 AAA가 로드되지 않은 것을 확인할 수 있습니다

    회신하다
    0
  • PHP中文网

    PHP中文网2017-04-18 10:54:20

    여기서 다루어야 할 두 가지 개념이 있습니다.

    1. 클래스 로딩 메커니즘

    2. Java, 컴파일러, 바이트코드, JVM 사양 및 구현.

    클래스 로딩은 클래스 로더(Classloader)를 통해 완료됩니다. 구체적인 로딩 전략은 JVM의 구체적인 구현에 따라 다릅니다. 일반적으로 두 가지 유형으로 나눌 수 있습니다.

    1. 다른 클래스에서 참조하는 한 로딩이 필요합니다.

    2. 지연 로딩, 클래스에 액세스할 때 로딩.

    Java, 컴파일러, 바이트코드 및 JVM에는 고유한 사양이 있으며 사양을 통해 함께 작동합니다.

    컴파일 버튼은 Java 코드를 표준화된 바이트코드 파일로 컴파일합니다. 각 클래스(외부 클래스, 내부 클래스, 익명 클래스)는 별도의 바이트코드 파일(클래스 파일)로 컴파일되며 이때 JVM은 클래스를 로드합니다. , 이러한 클래스 파일에서 하나씩 로드됩니다.

    이제 코드로 돌아갑니다.

    Java 계층에서는 AAA와 Main 두 클래스를 하나의 파일에 넣습니다. 컴파일 후 컴파일러는 AAA.class와 Main.class라는 두 개의 클래스 파일을 생성합니다.
    두 클래스는 코드 구성 측면에서 함께 있지만 컴파일 후에는 독립적이며 Main은 AAA를 참조하지 않으므로 어떤 클래스 로딩 방법을 사용하더라도 클래스 AAA 로딩을 트리거하지 않습니다. AAA의 정적 코드 블록은 실행되지 않습니다.

    회신하다
    0
  • ringa_lee

    ringa_lee2017-04-18 10:54:20

    답변해주신 위 열정적인 네티즌분들께 진심으로 감사드립니다!

    확인

    AAA 클래스는 실제로 로드되지 않고 Main 클래스만 로드됩니다. (질문의 스크린샷: 네 번째 초기화 조건, 메인 클래스는 jvm에 의해 자동으로 로드됩니다.)

    으아악

    결론

    클래스의 정적 필드 | 코드 블록은 클래스가 로드될 때 실제로 초기화되거나 실행됩니다!

    확장

    클래스가 jvm에 의해 로드되었는지 어떻게 알 수 있나요?

    이 역시 제가 고민했던 문제입니다. 처음에는

    명령이 실행되는 한 클래스가 jvm에 의해 로드될 것이라고 생각했습니다. 실제로는 그렇지 않습니다. 명령은 javac 파일을 jvm이 이해할 수 있는 .java 파일로만 변환합니다. .class

    그럼 클래스가 jvm에 의해 로드되었는지 어떻게 알 수 있나요? "Java Virtual Machine에 대한 심층적인 이해: JVM 고급 기능 및 모범 사례 2판"과 네티즌들의 열광적인 답변에 따르면 언제 로드될지 명확한 시기가 정해지지 않았습니다!

    하지만! jvm

    에서는 클래스가 초기화되는 시점을 명확하게 규정하고 있습니다 - 위 스크린샷에는 4가지 타입이 있습니다! 클래스 로딩은 클래스 초기화보다 우선하므로 여기서는 일시적으로 이러한 상황이 클래스 로딩을 트리거하는 조건이라고 생각할 수 있습니다.

    오빠가 무식해서 부적절한 내용을 요약했네요 정정해주세요! 감사합니다

    회신하다
    0
  • PHPz

    PHPz2017-04-18 10:54:20

    Main.java와 AAA.java를 같은 폴더에 넣으세요.

    메인 함수에

    를 작성하세요. 으아악

    실행

    회신하다
    0
  • 大家讲道理

    大家讲道理2017-04-18 10:54:20

    메인 메서드가 실행되면 Main 클래스만 로드됩니다. Main 클래스에서는 AAA 클래스가 사용되지 않으며 AAA 클래스는 로드되지 않습니다. 동일한 파일을 사용하면 동시에 로드됩니다.

    회신하다
    0
  • 大家讲道理

    大家讲道理2017-04-18 10:54:20

    AAA 클래스는 다른 곳에서는 새로운 것이 아니며 그에 따라 정적 필드를 가져오거나 설정하지도 않고 정적 메서드를 호출하지도 않습니다.
    그래서 자동으로 초기화되지 않습니다.

    회신하다
    0
  • 迷茫

    迷茫2017-04-18 10:54:20

    은 두 개의 클래스에 배치됩니다. 공개로 선언된 클래스의 기본 클래스는 초기화는커녕 사용되지도 않고 로드되지도 않습니다.

    회신하다
    0
  • 취소회신하다