Java 기초 악 보 -- ClassLoader

--------------------------------------------------------------------------------------------------------------
참고: http://www.ibm.com/developerworks/cn/java/j-lo-classloader/index.html
--------------------------------------------------------------------------------------------------------------
 
요점
  • ClassLoader (클래스 로 더) 기본 개념: 자바 류 를 JVM 에 불 러 옵 니 다.자바 소스 프로그램 (자바 파일) 은 컴 파 일 러 를 통 해 자바 바이트 코드 (class 파일) 로 변환 되 며, 클래스 로 더 는 자바 바이트 코드 를 읽 고 자바. lang. class 클래스 로 변환 하 는 인 스 턴 스 를 담당 합 니 다.기본적으로 모든 종류의 로 더 는 java.lang.ClassLoader 클래스 의 인 스 턴 스 입 니 다. 
  • 자바. lang. ClassLoader 류 의 기본 적 인 직책 은 지정 한 클래스 의 이름 에 따라 해당 하 는 바이트 코드 를 찾 거나 생 성 한 다음 에 이 바이트 코드 에서 자바 류, 즉 java.lang.Class 류 의 인 스 턴 스 를 정의 하 는 것 이다.이외에 도 ClassLoader 자바 응용 에 필요 한 자원, 예 를 들 어 이미지 파일 과 프로필 등 을 불 러 오 는 일 도 맡 는 다.
  • ClassLoader 에서 로 딩 류 와 관련 된 방법: 

  •  
    방법 설명getParent()
    이 종류의 로 더 의 부모 클래스 로 더 를 되 돌려 줍 니 다.loadClass(String name)
    이름 이 name 인 클래스 를 불 러 옵 니 다. 되 돌아 온 결 과 는 java.lang.Class 클래스 의 인 스 턴 스 입 니 다.findClass(String name)
    이름 이 name 인 클래스 를 찾 으 면 java.lang.Class 클래스 의 인 스 턴 스 를 되 돌려 줍 니 다.findLoadedClass(String name)
    이름 이 name 인 불 러 온 클래스 를 찾 습 니 다. 되 돌아 온 결 과 는 java.lang.Class 클래스 의 인 스 턴 스 입 니 다.defineClass(String name, byte[] b, int off, int len)
    바이트 배열 b 의 내용 을 자바 류 로 바 꾸 고 돌아 온 결 과 는 java.lang.Class 류 의 인 스 턴 스 입 니 다.이 방법 은 final 으로 성명 되 었 다.resolveClass(Class<?> c)
    지정 한 자바 클래스 를 연결 합 니 다.
     
  • 자바 류 로 더 분류: 시스템 제공, 개발 자 작성.
  • 시스템 이 제공 하 는 로 더 는 주로 다음 과 같다.
  • 유도 클래스 로 더 (boottstrap class loader): 자바 의 핵심 라 이브 러 리 를 불 러 오 는 데 사 용 됩 니 다. 네 이 티 브 코드 로 이 루어 집 니 다. 계승 되 지 않 습 니 다 java.lang.ClassLoader .
  • 확장 클래스 로 더 (extensions class loader): 자바 의 확장 라 이브 러 리 를 불 러 옵 니 다.자바 가상 컴퓨터 의 구현 은 확장 라 이브 러 리 디 렉 터 리 를 제공 합 니 다.이 종류의 로 더 는 이 디 렉 터 리 에서 자바 류 를 찾 아 불 러 옵 니 다.
  • 시스템 클래스 로 더 (system class loader): 자바 응용 클래스 경로 (CLASSPATH) 에 따라 자바 류 를 불 러 옵 니 다.일반적으로 자바 애플 리 케 이 션 의 종 류 는 로 딩 을 완료 하고 ClassLoader.getSystemClassLoader() 을 통 해 얻 을 수 있 습 니 다.

  • 개발 자 는 계승 java.lang.ClassLoader 류 를 통 해 자신의 클래스 로 더 를 실현 할 수 있다.        클래스 캐리어 트 리 조직 구조 설명 도 는 다음 과 같다. Java基础恶补——ClassLoader_第1张图片 
  • 클래스 로 더 의 프 록 시 모드: 프 록 시 모드 는 자바 핵심 라 이브 러 리 의 유형 안전 을 확보 하기 위해 서 입 니 다.모든 자바 응용 프로그램 은 최소한 java.lang.Object 클래스 를 인용 해 야 합 니 다. 즉, 실행 할 때 java.lang.Object 클래스 를 JVM 에 불 러 와 야 합 니 다.프 록 시 모드 를 통 해 자바 핵심 라 이브 러 리 의 클래스 에 대한 로 딩 작업 은 유도 류 로 더 에 의 해 통일 적 으로 이 루어 집 니 다. 자바 응용 이 사용 하 는 것 은 모두 같은 버 전의 자바 핵심 라 이브 러 리 클래스 이 고 서로 호 환 되 는 것 을 보장 합 니 다.  서로 다른 클래스 로 더 는 같은 이름 의 클래스 에 추가 이름 공간 을 만 들 었 습 니 다.같은 이름 의 클래스 는 JVM 에 존재 할 수 있 으 며, 다른 클래스 로 불 러 오기 만 하면 됩 니 다.같은 종류의 로 더 를 불 러 오 는 클래스 간 에는 호 환 되 지 않 습 니 다. 이것 은 JVM 내부 에 서로 격 리 된 자바 클래스 공간 을 만 드 는 것 과 같 습 니 다.
  • 로 더 류 의 과정: 진정 으로 클래스 의 로 딩 작업 을 완성 하 는 것 은 호출 defineClass 을 통 해 이 루어 진 것 이다.시작 클래스 의 로드 과정 은 호출 loadClass 을 통 해 이 루어 집 니 다.전 자 는 하나의 정의 로 더 (defining loader) 라 고 부 르 고 후 자 는 초기 로 더 (initiating loader) 라 고 부른다.JVM 이 두 클래스 가 같은 지 판단 할 때 클래스 의 정의 로 더 를 사용 합 니 다.즉, 어떤 종류의 로 더 를 시작 하 는 지 는 중요 하지 않 으 며, 중요 한 것 은 이러한 종류의 로 더 를 최종 적 으로 정의 하 는 것 이다.두 종류의 로 더 의 관련 점 은 하나의 정의 로 더 는 다른 종류의 초기 로 더 를 참조 하 는 것 입 니 다.예 를 들 어 클래스 com.example.Outer 는 클래스 com.example.Inner 를 인용 하면 클래스 com.example.Outer 의 정의 로 더 가 시작 클래스 com.example.Inner 의 로드 과정 을 책임 집 니 다.방법 loadClass() 이 던 진 것 은 java.lang.ClassNotFoundException 이상 이다.방법 defineClass() java.lang.NoClassDefFoundError 이상 을 던 졌 다.  클래스 로 더 는 클래스 를 성공 적 으로 불 러 온 후에 얻 은 java.lang.Class 클래스 의 인 스 턴 스 를 캐 시 합 니 다.다음 에 이 종 류 를 불 러 오 라 고 요청 할 때 클래스 로 더 는 캐 시 클래스 의 인 스 턴 스 를 직접 사용 합 니 다. 다시 불 러 오 려 고 하지 않 습 니 다.즉, 하나의 클래스 로 더 인 스 턴 스 에 있어 같은 이름 의 클래스 는 한 번 만 불 러 옵 니 다. 즉, loadClass 방법 은 중복 호출 되 지 않 습 니 다.
  • 스 레 드 컨 텍스트 클래스 로 더: 스 레 드 컨 텍스트 클래스 로 더 (context class loader) 는 JDK 1.2 부터 도입 되 었 습 니 다.클래스 java.lang.Thread 의 방법 getContextClassLoader() setContextClassLoader(ClassLoader cl) 스 레 드 를 가 져 오고 설정 하 는 컨 텍스트 클래스 로 더 입 니 다.setContextClassLoader(ClassLoader cl) 방법 으로 설정 하지 않 으 면 스 레 드 는 부모 스 레 드 의 컨 텍스트 클래스 로 더 를 계승 합 니 다.자바 가 실행 중인 초기 스 레 드 의 컨 텍스트 클래스 로 더 는 시스템 클래스 로 더 입 니 다.스 레 드 에서 실행 되 는 코드 는 클래스 와 자원 을 불 러 올 수 있 습 니 다.
  • Class. forName: 정적 방법 으로 클래스 를 불 러 올 수 있 습 니 다.
  • 클래스 로 더 와 웹 용기: 웹 용기 의 클래스 로 더 의 실현 방식 은 일반적인 자바 응용 과 다르다.웹 용기 마다 구현 방식 이 달라 질 수 있다.Apache Tomcat 의 경우 웹 애플 리 케 이 션 마다 해당 하 는 클래스 로 더 인 스 턴 스 가 있 습 니 다.이 종류의 로 더 도 프 록 시 모드 를 사용 합 니 다. 다른 것 은 먼저 어떤 종 류 를 불 러 오 려 고 시도 하 는 것 입 니 다. 부모 클래스 에 로 더 를 불 러 오 는 것 을 찾 을 수 없다 면.이것 은 자바 Servlet 규범 에서 추천 하 는 방법 으로 웹 응용 자체 의 우선 순위 가 웹 용기 가 제공 하 는 클래스 보다 높 도록 하 는 것 이 목적 이다.이러한 프 록 시 모드 의 예 외 는 자바 핵심 라 이브 러 리 의 종 류 는 검색 범위 안에 있 지 않다 는 것 이다.자바 핵심 라 이브 러 리 의 유형 안전 을 위해 서다.
  • 클래스 로 더 와 OSGi: OSGi™ 자바 의 동적 모듈 시스템 입 니 다.이 는 개발 자 에 게 서비스 와 구성 요 소 를 기반 으로 하 는 운영 환경 을 제공 하고 소프트웨어 의 생명 주 기 를 관리 하 는 표준 방식 을 제공한다.Eclipse 는 OSGi 기술 을 바탕 으로 구 축 된 것 이다. 

  • ClassLoader 에 대한 학습 노트
    Java基础恶补——ClassLoader_第2张图片
    Java基础恶补——ClassLoader_第3张图片
     
     
    관련 문제
    1.  Q: 클래스 로 더 를 구현 하 십시오.    A:  파일 시스템 클래스 로 더 코드 는 다음 과 같 습 니 다.
    package com.example; 
    
    public class Sample { 
        private Sample instance; 
    
        public void setSample(Object instance) { 
            this.instance = (Sample) instance; 
        } 
    }
    
    public void testClassIdentity() { 
        String classDataRootPath = "C:\\workspace\\Classloader\\classData"; 
        FileSystemClassLoader fscl1 = new FileSystemClassLoader(classDataRootPath); 
        FileSystemClassLoader fscl2 = new FileSystemClassLoader(classDataRootPath); 
        String className = "com.example.Sample"; 	
        try { 
            Class<?> class1 = fscl1.loadClass(className); 
            Object obj1 = class1.newInstance(); 
            Class<?> class2 = fscl2.loadClass(className); 
            Object obj2 = class2.newInstance(); 
            Method setSampleMethod = class1.getMethod("setSample", java.lang.Object.class); 
            setSampleMethod.invoke(obj1, obj2); 
        } catch (Exception e) { 
            e.printStackTrace(); 
        } 
    }

     
     일반적으로 자신 이 개발 한 클래스 로 더 는 복사 findClass(String name) 방법 만 있 으 면 되 며, 복사 loadClass() 방법 은 없 는 것 이 좋다.
     
    2.  Q: 다음 코드 를 실행 하면 어떤 상황 이 발생 합 니까? 
    public class FileSystemClassLoader extends ClassLoader { 
    
        private String rootDir; 
    
        public FileSystemClassLoader(String rootDir) { 
            this.rootDir = rootDir; 
        } 
    
        protected Class<?> findClass(String name) throws ClassNotFoundException { 
            byte[] classData = getClassData(name); 
            if (classData == null) { 
                throw new ClassNotFoundException(); 
            } 
            else { 
                return defineClass(name, classData, 0, classData.length); 
            } 
        } 
    
        private byte[] getClassData(String className) { 
            String path = classNameToPath(className); 
            try { 
                InputStream ins = new FileInputStream(path); 
                ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
                int bufferSize = 4096; 
                byte[] buffer = new byte[bufferSize]; 
                int bytesNumRead = 0; 
                while ((bytesNumRead = ins.read(buffer)) != -1) { 
                    baos.write(buffer, 0, bytesNumRead); 
                } 
                return baos.toByteArray(); 
            } catch (IOException e) { 
                e.printStackTrace(); 
            } 
            return null; 
        } 
    
        private String classNameToPath(String className) { 
            return rootDir + File.separatorChar 
                    + className.replace('.', File.separatorChar) + ".class"; 
        } 
    }

     
    A:  운행 시 이상 java.lang.ClassCastException 을 던 집 니 다.두 대상 obj1 obj2 의 클래스 이름 은 같 지만, 이 두 종 류 는 서로 다른 클래스 의 인 스 턴 스 로 불 러 오기 때문에 JVM 에 의 해 동일 하 다 고 여 겨 지지 않 는 다.
           JVM 은 두 자바 류 가 같은 지 어떻게 판단 합 니까? 클래스 의 전체 이름 이 같은 지 뿐만 아니 라 이러한 종류의 로 더 를 불 러 오 는 것 이 같은 지, 둘 다 같은 경우 에 만 두 가지 유형 이 같다 고 생각 합 니 다.같은 바이트 코드 라 도 서로 다른 종류의 로 더 에 불 러 온 후에 얻 은 클래스 는 다르다.
     
    3.  Q: 사용자 정의 클래스 로 더 의 응용 장 소 를 말씀 해 주 시 겠 습 니까? 
     A: 1) 자바 바이트 코드 (. class 파일) 를 서버 에 저장 하고 클 라 이언 트 는 네트워크 를 통 해 바이트 코드 를 가 져 와 실행 합 니 다.버 전이 업데이트 되 었 을 때 서버 에 저 장 된 파일 만 교체 하면 됩 니 다.
         2) 응용 프로그램 은 네트워크 를 통 해 자바 류 의 바이트 코드 를 전송 하고 안전성 을 확보 하기 위해 이 바이트 코드 들 은 암호 화 처 리 를 거 쳤 다.이 럴 때 암호 화 된 바이트 코드 를 네트워크 주소 에서 읽 고 복호화 와 검증 을 한 다음 JVM 에서 실행 할 클래스 를 정의 해 야 합 니 다.

    좋은 웹페이지 즐겨찾기