자바 클 라 스 파일 컴 파일 로 딩 과정 을 인 스 턴 스 로 분석 합 니 다.

1.자바 인 코딩 부터 실행 까지
우선 자바 가 어떻게 인 코딩 에서 실행 되 는 지 볼 까요?우 리 는 x.java 파일 이 javac 명령 을 실행 하면 x.class 파일 이 될 수 있 습 니 다.자바 명령 을 호출 할 때 class 파일 은 메모리 에 불 러 옵 니 다.이 과정 을 classloader 라 고 합 니 다.일반적으로 우리 가 코드 를 쓸 때 자바 라 이브 러 리 를 사용 하기 때문에 불 러 올 때 자바 라 이브 러 리 와 관련 된 클래스 도 메모리 에 불 러 옵 니 다.마 운 트 가 완료 되면 바이트 디 스 플레이 와 JIT 인 스 턴 트 컴 파일 러 를 호출 하여 설명 과 컴 파일 을 진행 합 니 다.컴 파일 이 끝 난 후 실행 엔진 에서 시작 합 니 다.실행 엔진 아래 에 대응 하 는 것 은 운영 체제 하드웨어 입 니 다.다음 그림 은 대체적인 절차 이다.

자바 는 크로스 플랫폼 의 언어 라 고 하 는데 JVM 은 크로스 언어 플랫폼 이 라 고 할 수 있다.
질문 이 있 습 니 다.자바 는 실행 을 설명 하 는 것 입 니까?컴 파일 실행 을 설명 하 는 것 입 니까?답:해석 과 컴 파일 은 혼합 할 수 있 습 니 다.특히 자주 사용 하 는 코드 나 코드 가 사용 하 는 횟수 가 매우 많 을 때 하나의 실시 간 컴 파일 을 로 컬 컴 파일 로 만 들 면 어느 정도 효율 을 높 일 수 있 습 니 다.
자바 가상 머 신 은 어떻게 이렇게 많은 언어 를 위 에서 실행 할 수 있 습 니까?관건 은 class 파일 입 니 다.모든 언어 가 class 파일 로 컴 파일 되 고 class 파일 의 규범 에 부합 하면 자바 가상 머 신 에서 실행 할 수 있 습 니 다.
2.class 파일 의 로드 과정 을 자세히 설명 합 니 다.
다음은 클 라 스 파일 이 하 드 디스크 에서 메모리 까지 어떻게 실행 되 는 지 설명 한다.
클래스 로드 는 주로 세 가지 과정 이 있 습 니 다.loading,linking,initializing;그 중에서 linking 은 세 가지 절차 로 나 뉘 는데 그것 이 바로 verification,preparation,resolution 이다.

1、우선 Loading 은 무슨 뜻 인가요?클래스 의 가격 을 메모리 에 로드 하 는 것 입 니 다.
2.다음 링크 는 세 단계 로 나 뉜 다.
  • verification 은 불 러 온 class 파일 이 class 파일 표준 에 부합 되 는 지 확인 하 는 데 사 용 됩 니 다.부합 되 지 않 으 면 바로 거 부 됩 니 다
  • preparation 은 class 파일 의 정적 변 수 를 초기 값 이 아니 라 기본 값 으로 부여 합 니 다.예 를 들 어 static int i=8;이 단 계 는 i 대 가 를 8 로 하 는 것 이 아니 라 기본 값 0 으로 하 는 것 입 니 다
  • resolution 은 class 파일 상수 탱크 에서 사용 하 는 기호 인용 을 직접 메모리 주소 로 변환 하여 접근 할 수 있 는 내용 입 니 다
  • 3.initializing 은 초기 화 되 고 정적 변 수 는 이 럴 때 초기 값 으로 대 입 됩 니 다.
    다음은 클래스 로 딩 과정의 간략화 그림 입 니 다.

    클래스 로 더 의 로드 과정 은 서로 다른 차원 으로 불 러 옵 니 다.서로 다른 클래스 로 더 는 서로 다른 class 파일 을 불 러 옵 니 다.Bootstrap>Extension>application>Custom(사용자 정의 클래스 로 더)
    1.첫 번 째 클래스 로 더 의 단 계 는 Bootstrap 을 시작 클래스 로 더 라 고 부 르 며 자바 클래스 로 더 계층 의 맨 위 클래스 로 더 입 니 다.JDK 의 핵심 라 이브 러 리 를 불 러 옵 니 다.
    2.두 번 째 클래스 로 더 의 단 계 는 Extension 은 확장 클래스 를 불 러 오 는 데 사 용 됩 니 다.주로 자바 의 확장 라 이브 러 리 를 불 러 옵 니 다.기본 으로 JAVA 를 불 러 옵 니 다.HOME/jre/lib/ext/디 렉 터 리 에 있 는 모든 jar 패키지 입 니 다.
    3.세 번 째 클래스 로 더 의 단 계 는 응용 프로그램 을 시스템 클래스 로 더 라 고도 부 릅 니 다.JVM 이 시 작 될 때 명령 자바 에 있 는 classpath 나 java.class.path 시스템 속성 이나 CLASSPATH 운영 체제 속성 이 지정 한 JAR 클래스 패키지 와 클래스 경 로 를 불 러 옵 니 다.
    4.세 번 째 클래스 로 더 의 단 계 는 사용자 정의 ClassLoader(사용자 정의 로 더)입 니 다.
    
    package com.example.demo.classloader;
    
    public class ClassLoaderScope {
      public static void main(String[] args) {
        System.out.println("-------------------Bootstrap   -------------------");
        String property = System.getProperty("sun.boot.class.path");
        String s = property.replaceAll(";", System.lineSeparator());
        System.out.println(s);
    
        System.out.println("-------------------Ext   -------------------");
    
        String property1 = System.getProperty("java.ext.dirs");
        String s1 = property1.replaceAll(";", System.lineSeparator());
        System.out.println(s1);
    
        System.out.println("-------------------App   -------------------");
    
        String property2 = System.getProperty("java.class.path");
        String s2 = property2.replaceAll(";", System.lineSeparator());
        System.out.println(s2);
      }
    }
        /**          */
        //E:\JDK\jdk1.8\jre\lib\resources.jar
        //E:\JDK\jdk1.8\jre\lib\rt.jar
        //E:\JDK\jdk1.8\jre\lib\sunrsasign.jar
        //E:\JDK\jdk1.8\jre\lib\jsse.jar
        //E:\JDK\jdk1.8\jre\lib\jce.jar
        //E:\JDK\jdk1.8\jre\lib\charsets.jar
        //E:\JDK\jdk1.8\jre\lib\jfr.jar
        //E:\JDK\jdk1.8\jre\classes
        //----------------------------------------------
        //E:\JDK\jdk1.8\jre\lib\ext
        //C:\Windows\Sun\Java\lib\ext
        //----------------------------------------------
        //E:\JDK\jdk1.8\jre\lib\charsets.jar
        //E:\JDK\jdk1.8\jre\lib\deploy.jar
        //E:\JDK\jdk1.8\jre\lib\ext\access-bridge-64.jar
        //E:\JDK\jdk1.8\jre\lib\ext\cldrdata.jar
        //E:\JDK\jdk1.8\jre\lib\ext\dnsns.jar
        //E:\JDK\jdk1.8\jre\lib\ext\jaccess.jar
        //E:\JDK\jdk1.8\jre\lib\ext\jfxrt.jar
    특히 주의해 야 할 것 은 이 등급 관 계 는 계승 되 지 않 은 관계 가 안에 있 고 순수한 문법 적 계승 일 뿐이다.
    다음 그림 은 클래스 로 딩 의 전 과정 입 니 다:
    비교적 통속 적 인 말로 이 과정 을 설명 합 니 다.불 러 올 클래스 가 있 을 때 먼저 이 클래스 가 메모리 에 불 러 왔 는 지 판단 하고 불 러 올 지 여 부 를 판단 하 는 과정 은 순서 가 있 습 니 다.자신 이 정의 한 클래스 로 더 가 있 으 면 custom class loader 의 cache(캐 시)에서 불 러 왔 는 지 여 부 를 찾 습 니 다.불 러 왔 으 면 결 과 를 직접 되 돌려 줍 니 다.그렇지 않 으 면 App 의 cache 에서 찾 습 니 다.만약 에 존재 하지 않 으 면 Extension 에서 찾 습 니 다.존재 하지 않 으 면 직접 되 돌아 갑 니 다.부모 로 더 에서 Bootstrap 맨 위 까지 계속 찾 습 니 다.만약 에 찾 지 못 하면 로 더 가 이 종 류 를 불 러 온 적 이 없습니다.해당 하 는 로 더 를 불 러 와 야 합 니 다.먼저 이 클래스 가 자신의 로드 범위 내 에 있 는 지 확인 하고 결 과 를 직접 불 러 오 는 것 이 라면 계속 아래로 위임 하지 않 으 면 최 하급 까지 유추 하고 최종 적 으로 불 러 오지 못 하면 이상 Class NotFoundException 을 버 리 는 것 이 부모 위임 모델 입 니 다.

    부모 위임 방식 이해 하기:
    1.부모 로 더:클래스 로 더 의 로 더 도 아니 고 클래스 로 더 의 부모 로 더 도 아 닙 니 다.
    
    package com.example.demo.classloader;
    
    /**
     *                 
     */
    public class ParentAndChild {
      public static void main(String[] args) {
        //AppClassLoader
        ClassLoader classLoader = ParentAndChild.class.getClassLoader();
        System.out.println(classLoader);
    
        //null   AppClassLoader      ExtClassLoader   Bootstrap
        ClassLoader appclassLoader = ParentAndChild.class.getClassLoader().getClass().getClassLoader();
        System.out.println(appclassLoader);
    
        //ExtClassLoader  AppClassLoader      ExtClassLoader
        ClassLoader parent = ParentAndChild.class.getClassLoader().getParent();
        System.out.println(parent);
    
        //null
        ClassLoader parentparent = ParentAndChild.class.getClassLoader().getParent().getParent();
        System.out.println(parentparent);
    
        //null
        ClassLoader parentparentparent = ParentAndChild.class.getClassLoader().getParent().getParent().getParent();
        System.out.println(parentparent);
    
        /**    */
        //sun.misc.Launcher$AppClassLoader@18b4aac2
        //null
        //sun.misc.Launcher$ExtClassLoader@23fc625e
        //null
        //Exception in thread "main" java.lang.NullPointerException at com.example.demo.classloader.ParentAndChild.main(ParentAndChild.java:22)
      }
    }
    2.부모 위임:그 작업 원 리 는 만약 에 하나의 클래스 로 더 가 클래스 로 더 요청 을 받 았 다 면 직접 불 러 오지 않 고 아래 에서 위로 올 라 가 는 최상 위 클래스 로 더 가 불 러 왔 는 지 찾 는 것 입 니 다.불 러 오 면 불 러 오지 않 아 도 됩 니 다.불 러 오지 않 았 다 면 위 에서 아래로 불 러 오 는 범위 에 속 하 는 지,속 하면 불 러 옵 니 다.만약 에 속 하지 않 으 면 아래 에 의뢰 를 하고 클래스 가 불 러 올 때 까지 성공 이 라 고 할 수 있 습 니 다.불 러 오 는 데 성공 하지 못 하면 이상 classnotfoundexeption 을 던 집 니 다.이것 을 부모 위임 이 라 고 합 니 다.
    3.왜 양친 위임 방식 을 해 야 합 니까?
    주로 안전 을 위해 서 입 니 다.여 기 는 반증 법 을 사용 할 수 있 습 니 다.모든 종류의 로 더 가 클 라 스 를 메모리 에 불 러 올 수 있다 면 자바.lang.string 을 불 러 올 수 있 습 니 다.포장 할 때 비밀 번 호 를 String 대상 으로 저장 하고 비밀 번 호 를 몰래 자신의 메 일 로 보 내 면 안전 에 문제 가 생 길 수 있 습 니 다.
    3.사용자 정의 클래스 로 더
    
    package com.example.demo.classloader;
    
    public class ClassLoaderByHand {
      public static void main(String[] args) throws ClassNotFoundException {
        Class<?> clazz = ClassLoaderByHand.class.getClassLoader().
            loadClass("com.example.demo.threaddemo.juc_002.Account");
        String name = clazz.getName();
        System.out.println(name);
    
      }
    }
    
      /**
      *     
      */
      //com.example.demo.threaddemo.juc_002.Account
    코드 실행 결 과 를 보면 클래스 를 불 러 오 려 는 것 을 알 수 있 습 니 다.클래스 Loader 의 로드 클래스()방법 을 호출 하면 이 클래스 를 메모리 에 불 러 올 수 있 습 니 다.불 러 오 는 것 이 완료 되면 클래스 클래스 의 대상 을 되 돌려 줍 니 다.
    하 드 디스크 에서 이러한 종류의 소스 코드 를 찾 아 메모리 에 로드 하 는 동시에 Class 대상 을 생 성 합 니 다.상기 애플 릿 은 ClassLoaderby Hand 을 통 해 그의 로 더 AppClassLoader 를 찾 은 다음 에 loadclas()방법 을 호출 하여 Account 류 를 불 러 오고 clazz 대상 으로 돌아 가 며 clazz.getName()방법 으로 Account 류 를 정상적으로 되 돌려 줍 니 다.
    언제 우 리 는 클래스 를 불 러 올 것 을 스스로 정의 해 야 합 니까?
    열 배치 시 이전에 불 러 온 클래스 를 제거 한 다음 사용자 정의 클래스 로 더 를 다시 불 러 옵 니 다.
    spring 의 동적 에이전트,새로운 class 가 필요 할 때 메모리 에 로드 합 니 다.
    원본 코드 를 살 펴 보 겠 습 니 다.로 딩 과정 에서 가장 중요 한 것 은 ClassLoader 의 loaderClass()방법 입 니 다.
    위 에서 준 클래스 로드 과정의 도 해 를 결합 하여 보 는 것 이 더 쉬 울 것 입 니 다.
    
    protected Class<?> loadClass(String name, boolean resolve)
          throws ClassNotFoundException
      {
        synchronized (getClassLoadingLock(name)) {
          /**
           *         findLoadedClass()             
           *           
           *         null      
           */
          // First, check if the class has already been loaded
          Class<?> c = findLoadedClass(name);
          if (c == null) {
            long t0 = System.nanoTime();
            try {
              //                     Bootstrap    loadClass()
              if (parent != null) {
                c = parent.loadClass(name, false);
              } else {
                //                 Bootstrap Class Loader,                 
                c = findBootstrapClassOrNull(name);
              }
            } catch (ClassNotFoundException e) {
              // ClassNotFoundException thrown if class not found
              // from the non-null parent class loader
            }
            //              
            if (c == null) {
              // If still not found, then invoke findClass in order
              // to find the class.
              long t1 = System.nanoTime();
              //     findClass()
              c = findClass(name);
    
              // this is the defining class loader; record the stats
              sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
              sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
              sun.misc.PerfCounter.getFindClasses().increment();
            }
          }
          if (resolve) {
            resolveClass(c);
          }
          return c;
        }
      }
    이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

    좋은 웹페이지 즐겨찾기