JVM 클래스 로더 분류 및 분석

30603 단어
클래스 로더
  • 클래스 캐리어
  • 류 캐리어의 분류
  • 부팅 클래스 로더(부트 클래스 로더, Bootstra ClassLoader)
  • 확장 클래스 로더(Extension ClassLoader)
  • 사용자 정의 클래스 로더
  • 클래스 로더
    클래스 로더의 분류
  • JVM은 부트 클래스 로더(Bootstrap ClassLoader)와 사용자 정의 클래스 로더(User-definded ClassLoader) 등 두 가지 종류의 클래스 로더를 지원한다
  • 개념적으로 볼 때 사용자 정의 클래스 로더는 프로그램에서 개발자가 정의한 클래스 로더이지만 자바 가상 기기 규범에서 이렇게 정의하지 않고 추상적인 클래스인 클래스 로더에서 파생된 모든 클래스 로더를 사용자 정의 클래스 로더로 구분한다.
  • 클래스 마운트의 유형을 어떻게 구분하든지 간에 프로그램에서 가장 흔히 볼 수 있는 클래스 마운트는 시종 3개에 불과하다. ** 유도 클래스 마운트, 확장 클래스 마운트, 시스템 클래스 마운트. **그 중에서 가이드 클래스 로더를 제외하고 나머지는 ClassLoader에서 파생된 클래스, 즉 사용자 정의 클래스 로더이다.

  • 클래스 마운트 가져오기 코드 설명
    public class ThreadTest {
        public static void main(String[] args) {
            //          sun.misc.Launcher$AppClassLoader@18b4aac2
            ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
            System.out.println(systemClassLoader);
    
            //             sun.misc.Launcher$ExtClassLoader@1540e19d
            ClassLoader extClassLoader = systemClassLoader.getParent();
            System.out.println(extClassLoader);
    
            //             null
            ClassLoader bootstrapClassLoader = extClassLoader.getParent();
            System.out.println(bootstrapClassLoader);
    
            //            sun.misc.Launcher$AppClassLoader@18b4aac2
            ClassLoader classLoader = ThreadTest.class.getClassLoader();
            System.out.println(classLoader);
        }
    }
    

    클래스 로더 시작(부트 클래스 로더, Bootstra ClassLoader)
  • 이 클래스는 C/C++ 언어로 실행되며 JVM 내부에 끼워넣기
  • 이 로더는 자바의 핵심 라이브러리(JAVA HOME/jre/lib/rt.jar,resources.jar 또는sun.boot.class.path 경로 아래의 내용)를 불러오는 데 사용되며, JVM의 자체 요구 클래스
  • 를 제공하는 데 사용된다.
  • java에서 계승하지 않습니다.lang.ClassLoader, 상위 클래스 로더가 없습니다.
  • 확장 클래스와 응용 프로그램 클래스 마운트를 불러오고 부모 클래스 마운트로 지정
  • 안전을 고려하여 BootStrap 부팅 클래스 마운트는 가방의 이름이 자바,javax,sun 등으로 시작하는 클래스
  • 입니다.
    확장 클래스 로더(Extension ClassLoader)
  • Java 언어는 sun.misc.Launcher$ExtClassLoader 구현
  • ClassLoader 클래스
  • 에서 파생
  • 부류 마운트는 부팅 클래스 마운트
  • java에서.ext.dirs 시스템 속성이 지정한 디렉터리에 라이브러리를 불러오거나, JDK의 잡기 디렉터리에 있는 jre/lib/ext 하위 디렉터리 (확장 디렉터리) 에서 라이브러리를 불러옵니다.사용자가 만든 JAR을 보조 디렉토리에 두면 확장 클래스 로더가 자동으로 로드됩니다.

  • 클래스 로더에 대한 테스트는 다음과 같습니다.
    package com.classload.chapter01;
    
    import sun.misc.Launcher;
    import sun.security.ec.CurveDB;
    
    import java.net.URL;
    
    public class ThreadTest {
        public static void main(String[] args) {
            System.out.println("=====      =====");
            URL[] urLs = Launcher.getBootstrapClassPath().getURLs();
            for (URL url : urLs) {
                System.out.println(url);
            }
    
            System.out.println("=====      =====");
            String property = System.getProperty("java.ext.dirs");
            for (String path : property.split(";")) {
                System.out.println(path);
            }
    
            System.out.println("=====      =====");
            System.out.println("    : CurvDB");
            ClassLoader classLoader = CurveDB.class.getClassLoader();
            System.out.println(classLoader);
        }
    }
    #     
    =====      =====
    file:/D:/JDK/jdk1.8.0_131/jre/lib/resources.jar
    file:/D:/JDK/jdk1.8.0_131/jre/lib/rt.jar
    file:/D:/JDK/jdk1.8.0_131/jre/lib/sunrsasign.jar
    file:/D:/JDK/jdk1.8.0_131/jre/lib/jsse.jar
    file:/D:/JDK/jdk1.8.0_131/jre/lib/jce.jar
    file:/D:/JDK/jdk1.8.0_131/jre/lib/charsets.jar
    file:/D:/JDK/jdk1.8.0_131/jre/lib/jfr.jar
    file:/D:/JDK/jdk1.8.0_131/jre/classes
    =====      =====
    D:\JDK\jdk1.8.0_131\jre\lib\ext
    C:\Windows\Sun\Java\lib\ext
    =====      =====
        : CurvDB
    sun.misc.Launcher$ExtClassLoader@29453f44
    

    상기 코드의 설명: 1. 가이드 클래스 마운트의 스캐닝 디렉터리를 얻을 때sun.misc.Launcher.getBootstrapClassPath().getURLs(); 방법으로 스캐닝한 모든jar 패키지의 디렉터리를 얻을 때2,확장 클래스 마운트의 스캐닝 경로를 얻을 때System.getProperty("java.ext.dirs"); 방법은 시스템 속성의java이기 때문이다.tt.dirs에서 클래스 라이브러리 3을 불러오고 클래스를 사용하여 클래스를 테스트합니다. 클래스는classgetClassLoader 방법을 사용합니다.CurvDB는 D:\JDK\jdk1.8.0_131\jre\lib\ext 디렉터리에 있는sunec 패키지의 클래스이기 때문에 클래스를 확장하는 클래스입니다.
    그런데 만약에 스트링이라는 핵심 가방 밑에 있는 류를 찾는다면?한번 해볼게요.
    public static void main(String[] args) {
            ClassLoader classLoader1 = String.class.getClassLoader();
            System.out.println(classLoader1);
    }
    
        :null
    

    핵심 패키지는 가이드 클래스 마운트이고, 가이드 클래스 마운트는 C와 C++로 작성되어 있기 때문에 얻을 수 없습니다.
    사용자 정의 클래스 로더
    사용자 정의 클래스 마운트의 실현 절차: 1. 개발자는 추상적인 클래스java에 따라lang.ClassLoader 클래스의 방식으로 자신의 클래스 마운트를 실현하여 수요를 만족시킵니다.2. JDK에서 1.2 이전에 사용자 정의 클래스 로더를 사용할 때 항상 클래스 로더 클래스를 계승하고 loadClass () 방법을 다시 써서 사용자 정의 클래스 로더를 실현하지만 JDK1.2 이후로loadCass () 방법을 덮어쓰는 것이 아니라 사용자 정의 클래스 불러오기 논리를findClass () 방법에 쓰는 것이 좋습니다.3. 사용자 정의 클래스 로더를 작성할 때 너무 복잡한 수요가 없으면 URLclass Loader 클래스를 직접 계승할 수 있다. 이렇게 하면findClass () 방법을 작성하는 기계가 바이트 코드를 가져오는 방식을 피할 수 있고 사용자 정의 클래스 로더의 작성이 더욱 간결하다.
    다음은 코드를 써서 이해해 봅시다.
    //CustomClassLoader.java 
    public class CustomClassLoader extends ClassLoader {
        private String path;
    
        /**
         * @param path      class     
         */
        public CustomClassLoader(String path) {
            this.path = path;
        }
        
        @Override
        protected Class<?> findClass(String name) throws ClassNotFoundException {
            try {
                byte[] result = getClassData();
                if(result == null) {
                    throw new FileNotFoundException();
                } else {
                    return defineClass(name, result, 0, result.length);
                }
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
            return super.findClass(name);
        }
    
        /**
         * @return    class       
         *
         *                    
         *           byte  
         *
         *          path   .class  
         */
        private byte [] getClassData() {
            File file = new File(path);
            if(file.exists()) {
                InputStream in = null;
                ByteArrayOutputStream out = null;
                try {
                    in = new FileInputStream(file);
                    out = new ByteArrayOutputStream();
    
                    int length = 0;
                    byte [] bytes = new byte[1024];
                    while ((length = in.read(bytes)) != -1) {
                        out.write(bytes, 0, length);
                    }
    
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    if(in != null) {
                        try {
                            in.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
                return out.toByteArray();
            } else {
                return null;
            }
        }
    }
    

    테스트 코드:
    public class ThreadTest {
        public static void main(String[] args) throws ClassNotFoundException {
            CustomClassLoader loader = new CustomClassLoader("E:\\IDEA\\JavaBase\\ClassLoad\\target\\classes\\com\\classload\\chapter01\\HelloLoader.class");
            Class<?> aClass = loader.loadClass("com.classload.chapter01.HelloLoader");
            System.out.println("     :" + aClass.getClassLoader());
            Object object = aClass.newInstance();
            System.out.println(object);
        }
    }
    
    #     :
         :sun.misc.Launcher$AppClassLoader@18b4aac2
    execute
    com.classload.chapter01.HelloLoader@677327b6
    

    1、우선 클래스의 경로를 사용하여 불러와야 합니다.class 파일,class 파일을 이진 그룹 2로 변환하고 이진 그룹과 파일의 패키지 이름 + 파일 이름에 따라classLoader 클래스의defineClass 방법을 호출하여 클래스의 불러오는 과정을 완성합니다
    클래스 불러오기가 완료되면 newInstance () 방법을 사용해서 클래스의 실례를 가져올 수 있으며 getClassLoader () 방법을 사용하면 클래스의 마운트기를 가져올 수 있습니다
    자, 클래스의 세 가지 마운트는 여기까지 쓰겠습니다. 끝까지 봐주셔서 감사합니다. 지지해 주셔서 감사합니다.참, 만약 어디에 잘못 썼는지 아래 평론 구역에서 나에게 말해 주세요.886

    좋은 웹페이지 즐겨찾기