자바 류 캐리어 계층 구조 원리 분석

7497 단어 자바종류로 더
클래스 로 더 의 계층 구조:
유도 클래스 로 더(boottstrap class loader)
자바 의 핵심 라 이브 러 리 불 러 오기(JAVAHOME/jre/lib/rt.jar 또는 sun.boot.class.path 경로 의 내용)은 네 이 티 브 코드 로 이 루어 집 니 다(C 로 이 루어 집 니 다).자바.lang.classLoader 에서 계승 되 지 않 습 니 다.
확장 클래스 와 응용 프로그램 클래스 로 더 를 불 러 오고 부모 클래스 로 더 를 지정 합 니 다.
확장 클래스 로 더(extensions class loader)
자바 의 확장 라 이브 러 리 불 러 오기(JAVAHOME/jre/lib/ext/*.jar 또는 java.ext.dirs 경로 의 내용)자바 가상 컴퓨터 의 구현 은 확장 라 이브 러 리 디 렉 터 리 를 제공 합 니 다.이 종류의 로 더 는 이 디 렉 터 리 에서 자바 류 를 찾 아 불 러 옵 니 다.
sun.miscLauncher$ExtClassLoader 가 있 습 니 다.자바.lang.ClassLoader 에서 계승 합 니 다.
응용 프로그램 클래스 로 더(application class loader)
자바 응용 클래스 경로(classpath,java.classs.path 경로)에 따라 지정 한 경로 의 클래스 를 불 러 옵 니 다.일반적으로 자바 응용 클래스 는 불 러 옵 니 다.
sun.misc.Launcher$AppClassLoader 에서 이 루어 집 니 다.java.lang.ClassLoader 에서 계승 합 니 다.
사용자 정의 클래스 로 더
개발 자 는 자바.lang.ClassLoader 류 를 계승 하 는 방식 으로 자신의 클래스 로 더 를 실현 하여 특수 한 수 요 를 만족 시 킬 수 있다.
설명:자바 에서 클래스 의 로 딩 은 부모 위탁 체 제 를 사용 하기 때문에 위의 몇 가지 로 딩 기 는 부자 관계 이 고 그 중에서 유도 류 로 딩 기 를 바탕 으로 합 니 다.
ClassLoader 클래스 소개
역할:
java.lang.ClassLoader 류 의 기본 적 인 직책 은 지정 한 클래스 의 이름 에 따라 해당 하 는 바이트 코드 를 찾 거나 생 성 한 다음 에 이 바이트 코드 에서 자바 류,즉 자바.lang.Class 류 의 인 스 턴 스 를 정의 하 는 것 입 니 다.
이 밖 에 도 ClassLoader 는 자바 응용 에 필요 한 자원 파일,예 를 들 어 이미지 파일 과 프로필 등 을 불 러 옵 니 다.
관련 방법:
  • getParent()이 클래스 의 부모 클래스 로 더 를 되 돌려 줍 니 다
  • loadclass(String name)이름 이 name 인 클래스 를 불 러 옵 니 다.결 과 는 java.lang.Class 클래스 의 인 스 턴 스
  • 입 니 다.
  • findClass(String name)에서 name 이라는 클래스 를 찾 았 습 니 다.결 과 는 java.lang.Class 클래스 의 인 스 턴 스
  • 입 니 다.
  • findLoadedclass(String name)이름 이 불 러 온 클래스 를 찾 습 니 다.결 과 는 자바.lang.Class 클래스 의 인 스 턴 스
  • 입 니 다.
  • defineClass(String name,byte[]b,int off,int len)는 바이트 배열 b 의 내용 을 자바 류 로 변환 하고 돌아 온 결 과 는 자바.lang.class 류 의 인 스 턴 스 입 니 다.이 방법 은 final 로 밝 혀 졌 다.4567918)
  • resolveClass(Class c)지정 한 자바 클래스 를 연결 합 니 다.
  • 코드 테스트 클래스 로 더:
    
    public class Demo02 {
      public static void main(String[] args) {
        System.out.println(ClassLoader.getSystemClassLoader());
        System.out.println(ClassLoader.getSystemClassLoader().getParent());;
        System.out.println(ClassLoader.getSystemClassLoader().getParent().getParent());;
      }
    }
    출력:
    sun.misc.Launcher$AppClassLoader@1016632
    sun.misc.Launcher$ExtClassLoader@dc6a77
    null
    순서대로 로 더,확장 로 더,가이드 로 더 를 사용 합 니 다.
    클래스 로 더 의 프 록 시 모드:
    프 록 시 모드:지정 한 종 류 를 불 러 오 는 다른 로 더 에 게 건 네 줍 니 다.
    양친 위탁 메커니즘:
    특정한 클래스 로 더 는 로 더 류 의 요청 을 받 았 을 때 먼저 로 더 임 무 를 아버지 클래스 로 더 에 의뢰 하여 가장 높 은 할아버지 세대 까지 거 슬러 올 라 가 는 것 이다.만약 에 아버지 클래스 로 더 가 클래스 로 더 임 무 를 완성 할 수 있다 면 성공 적 으로 돌아 갈 수 있다.부모 클래스 로 더 가 이 로 딩 작업 을 수행 할 수 없 을 때 만 스스로 불 러 옵 니 다.
    부모 의뢰 체 제 는 자바 핵심 라 이브 러 리 의 유형 안전 을 확보 하기 위 한 것 입 니 다.
    클래스 로 더 는 로 딩 류 뿐만 아니 라 안전 의 가장 기본 적 인 장벽 이기 도 합 니 다.
    부모 위탁 체 제 는 대리 모델 의 하나 이다.
    모든 종류의 로 더 가 부모 위탁 체 제 를 사용 하 는 것 은 아니다.
    tomcat 서버 클래스 로 더 도 프 록 시 모드 를 사용 합 니 다.다른 것 은 먼저 어떤 종 류 를 불 러 오 려 고 시도 하 는 것 입 니 다.부모 클래스 로 더 를 불 러 오 는 프 록 시 를 찾 지 못 하면.이것 은 일반 종류의 로 더 순서 와 반대 이다.
    사용자 정의 클래스 로 더 프로 세 스:
    계승:java.lang.ClassLoader
    우선 요청 한 형식 이 네 임 스페이스 에 불 러 왔 는 지 확인 하고 불 러 왔 으 면 되 돌려 줍 니 다.
    위임 클래스 는 부모 클래스 로 더 에 요청 을 불 러 옵 니 다.부모 클래스 로 더 가 완료 되면 부모 클래스 로 더 가 불 러 온 Class 인 스 턴 스 를 되 돌려 줍 니 다.
    이 종류의 로 더 의 findClass()방법 을 호출 하고 사제 가 해당 하 는 바이트 코드 를 가 져 옵 니 다.가 져 오 면 defineClass()가 져 오 는 형식 을 방법 영역 으로 가 져 옵 니 다.대응 하 는 바이트 코드 를 가 져 오지 못 하거나 다른 이유 로 실 패 했 을 경우,로드 클래스(),로드 클래스()에 이상 을 되 돌려 주 고,로드 프로 세 스 를 종료 합 니 다.
    주:두 개의 로 더 에 불 러 온 같은 클래스 입 니 다.Jvm 은 같은 클래스 라 고 생각 하지 않 습 니 다.
    예제 코드 는 다음 과 같다.
    
    package com.test;
    
    import java.io.ByteArrayOutputStream;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    
    /**
     *           
     * @author We.lxk
     *
     */
    public class FileSystemClassLoader extends ClassLoader{
      private String rootDir;
      
      public FileSystemClassLoader(String rootDir) {
        this.rootDir = rootDir;
      }
      
      private byte[] getClassData(String classname){    //com.test.User -> rootDir/com/test/User
        String path = rootDir +"/"+classname.replace(".", "/")+".class";
        //IOUtils                    
        InputStream is = null;
        ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
        try{
          is = new FileInputStream(path);
          
          byte[] buffer = new byte[1024];
          int temp = 0;
          while((temp=is.read(buffer))!=-1){
            baos.write(buffer, 0, temp);
          }
          return baos.toByteArray();
        }catch(Exception e){
          e.printStackTrace();
          return null;
        }finally{
            try {
              if(is!=null)
              is.close();
            } catch (IOException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
            }
            try {
              if(baos!=null)
              baos.close();
            } catch (IOException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
            }
        }
      }
      
      @Override
      public Class<?> loadClass(String name) throws ClassNotFoundException {
        Class<?> c = findLoadedClass(name);
        
        //              。    ,          。
        if(c!=null){
          return c;
        }else{
          ClassLoader parent = this.getParent();
          try{
            //System.out.println("hello");
            c = parent.loadClass(name);          //       
          }catch(Exception e){
            //e.printStackTrace();
          }
          if(c!=null){
            return c;
          }else{
            byte[] classData = getClassData(name);
            if(classData==null){
              throw new ClassNotFoundException();
            }else{
              c = defineClass(name, classData, 0, classData.length);
            }
          }
        }
        return c;
      }
    }
    테스트 코드:
    
    package com.test;
    
    /**
     *        FileSystemClassLoader 
     * @author We.lxk
     *
     */
    public class Demo03 {
      public static void main(String[] args) throws Exception {
        FileSystemClassLoader loader = new FileSystemClassLoader("D:/myJava");
        FileSystemClassLoader loader2 = new FileSystemClassLoader("D:/myJava");
        
        Class<?> c = loader.loadClass("com.test.Demos");
        Class<?> c2 = loader.loadClass("com.test.Demos");
        Class<?> c3 = loader2.loadClass("com.test.Demos");
        
        Class<?> c4 = loader2.loadClass("java.lang.String");
        Class<?> c5 = loader.loadClass("com.test.Demo");
        
        
        System.out.println(c.hashCode()+" "+c.getClassLoader());
        System.out.println(c2.hashCode()+" "+c2.getClassLoader());
        System.out.println(c3.hashCode()+" "+c3.getClassLoader());
        System.out.println(c4.hashCode()+" "+c4.getClassLoader());
        System.out.println(c5.hashCode()+" "+c5.getClassLoader());
        //System.out.println(.getClassLoader());
      }
    }
    이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

    좋은 웹페이지 즐겨찾기