Java에는 두 가지 유형의 클래스로드가 있으며, 하나는 사용자 정의이고 다른 하나는 JVM에 내장 된 부트 스트랩 클래스 로더입니다.
JVM에 내장 된 세 가지 유형의 클래스 로더, 즉 부트 스트랩 클래스 로더, 확장 클래스 로더 (예 : ExtClassLoader) 및 시스템 클래스 로더 (예 : AppClassLoader)가 있습니다.
JVM이로드되었을 때 부모 대의원에 대해 이야기하지 않겠습니다. Javaeye에 소개 된 기사가 많이 있습니다 ...
부트 스트랩 클래스 로더가 c로 작성되는 생성자를 개별적으로 볼 수 있습니다.
java.lang.classloader
보호 된 클래스 로더 (ClassLoader Parent) {Security = getSecurityManager () {inception.checkcre ateclassloader (); true} protected classloader () {security = system.getSecurityManager (); 초기화 = true;
이 생성자에는 두 개의 매개 변수가 있으며 생성자가 없습니다. 매개 변수가있는 생성자는이 클래스 로더의 부모 로더에 전달되는 반면, 매개 변수가없는 생성자는 getSystemClassloader ()에 의해 반환 된 클래스 로더를 GetSystemClassLoader ()를 살펴 보겠습니다
public static getsystemclassloader () {// if (scl == null) {return null); ccl = getCallerClassLoader (); if (! sclset) {if (scl! = null) New ImperalStateException ( "재귀 호출"); oops = null; // 값은 scl = l.getclassloader (); ............................. .... ...................................} sclset = true}} 여기의 부모 클래스 로더는 SCL이며 L.getClassLoader (), getClassLoader ()가 얻은 다음 소스 소스 코드를 살펴 봅니다.
개인 정적 런처 런처 = 새로운 런처 ();
Public Launcher getLauncher () {return 런처; );} catch (ioexception e) {new InternalError ( "확장 클래스 로더를 만들 수 없음"). 즉, GetSystemClassLoader는 AppClassLoader 로더를 반환합니다 스레드, 멀티 스레드에서 클래스로드로 인한 혼란을 방지합니다 (나는 이것을 직접 이해합니다). .................................................. ................................................ .. ..............} / * * 메인 애플리케이션을 시작하는 데 사용되는 클래스 로더를 반환합니다. 이것으로부터 우리는 AppClassLoader의 상위 로더가 ExtClassLoader이고 ExtClassLoader의 상위 로더는 무엇입니까? ExtClassLoader 생성자를 살펴 보겠습니다.
public extclassloader (file [] dirs)는 ioexception {getexturls (dirs), null, this.dirs = dirs;그의 상위 로더는 비어 있지만 그의 최상위 상위 클래스는 java.lang.classloader입니다.
보호 된 동기화 된 클래스 <?> loadclass (String Name, Boolean Resolve)는 classNotFoundException {// 클래스가 이미로드되었는지 확인하십시오 ! = null) {// 부모 로더를 호출하여 parent.loadclass (false) {// 부트 스트랩 클래스 로더를 호출합니다 ) {// findclass를 호출하십시오.여기서 FindBootstrapClass0은 클래스를로드하기 위해 가장 핵심 클래스 로더 인 부트 스트랩 클래스 로더를 호출하는 것입니다.
마지막으로 GetSystemClassLoader ()가 반환 한 클래스 로더가 AppClassLoader임을 알 수 있습니다.
Java 클래스 로더 메커니즘 분석
JDK 기본 클래스 로더
JDK는 기본적으로 다음 클래스 로더를 제공합니다
Bootstrp 로더
Bootstr 로더는 C ++ 언어로 작성되었습니다. Java 가상 머신이 시작된 후에는 주로 Java_home %/jre/lib, -xbootclass parameter로 지정된 경로를로드합니다. JRE/클래스.
ExtClassLoader
Bootstrp 로더는 ExtClassLoader를로드하고 ExtClassLoader의 상위 로더를 Bootstrp 로더로 설정합니다. ExtClassLoader는 Java, 특히 Sun.Launcher $ extclassloa der, ExtClassLoader가 주로 java_home %/jre/ext, ext, extconds. 이 모든 클래스는 java.ext.dirs 시스템 변수에 의해 지정된 경로의 경로 및 클래스 라이브러리에 따라 디렉토리입니다.
AppClassloader
Bootstrp 로더가 ExtClassLoader를로드하면 AppClassLoader가로드되고 AppClassLoader의 상위 로더가 ExtClassLoader로 지정됩니다. AppClassLoader는 Java로 작성됩니다. 구현 클래스는 Sun.launcher $ AppClassloader입니다. Java 프로그램의 기본 클래스 로더이기도 한 JAR 문서입니다.
요약하면, 그들 사이의 관계는 다음 그림에서 설명 할 수 있습니다.
부모 대표 모델
Java의 클래스 로더로드는 부모 대의원 메커니즘을 사용하여 클래스를로드 할 때 다음 단계가 채택됩니다.
현재 클래스 로더는 먼저이 클래스가 이미로드 된 클래스에서로드되었는지 확인합니다.
각 클래스 로더에는 자체로드 캐시가 있습니다. 클래스가로드되면 캐시에 넣고 다음에로드되면 직접 반환 할 수 있습니다.
클래스 로더 캐시를 찾을 수없는 경우, 상위 클래스 로더가이를로드하도록 위임된다. Bootstrp 클래스 로더의 방법.
모든 상위 클래스 로더가로드되지 않으면 현재 클래스 로더에 의해로드되어 다음에로드 요청이있을 때 직접 반환 할 수 있도록 자체 캐시에 넣습니다.
이것에 대해 말하면, Java가 왜 그러한 대표단 메커니즘을 채택합니까? 이 문제를 이해하기 위해 클래스 로더에 대한 또 다른 개념 "네임 스페이스"를 소개합니다. 즉, 특정 클래스를 결정하려면 클래스의 자격을 갖춘 이름이 필요 하고이 클래스 클래스 로더를로드하여 공동으로 결정합니다. 즉, 두 클래스의 완전히 자격을 갖춘 이름이 동일하더라도 다른 클래스 로더 가이 클래스를로드하기 때문에 JVM의 다른 클래스입니다. 네임 스페이스를 이해 한 후 대의원 모델을 살펴 보겠습니다. 대의원 모델을 채택한 후, 위에서 언급 한 바와 같이 다른 클래스 로더의 대화식 기능이 증가합니다. 당신의 프로그램은 그 안에 너무 많은 클래스 로더가 있으므로 이러한 클래스를 실제로 공유 할 수 있으므로 동일한 이름의 다른 클래스를로드 한 후 다른 클래스 로더로 인한 혼란을 피할 수 있습니다.
클래스 로더를 사용자 정의하는 방법
위에서 언급 한 기본 클래스 로더 외에도 Application은 클래스 로더를 사용자 정의 할 수 있습니다. 몇 가지 중요한 방법에주의를 기울여야합니다.
1. 클래스 방법
로드 클래스 메소드는 선언합니다
public class <?> loadclass (문자열 이름)는 classNotFoundException을 던집니다
위는로드 클래스 방법의 프로토 타입 선언입니다. 이 방법의 코드를 살펴보고 그것이 부모 대의원을 어떻게 구현하는지 알아 보겠습니다.
로드 클래스 메소드 구현
public class <?> loadclass (문자열 이름)는 classNotFoundException {return loadclass (name, false);} 던지기위에서 Loadclass 메소드가 loadcclass (이름, false) 메소드를 호출하는 것을 볼 수 있으므로 다른 loadclass 메소드의 구현을 살펴 보겠습니다.
클래스 loadclass (문자열 이름, 부울 결의)
보호 된 동기화 된 클래스 <?> loadclass (문자열 이름, 부울 resolve)는 classNotFoundException {// 첫 번째, 클래스가 이미로드되었는지 확인 c = findloadedClass (name); // 클래스가 (c =로로드되었는지 확인하십시오. = null) {try {if (parent! = null) {c = parent.loadclass (이름, false); } else {c = findbootstrapclass0 (name); // 상위 클래스 로더가 없으면 부트 스트랩 로더를로드하도록 위임}} catch (classNotFoundException e) {// 아직 찾을 수없는 경우 // to to에 findclass를 호출하십시오. 클래스를 찾으십시오. C. C. FindClass (이름); // 상위 클래스가로드되지 않으면 자체 FindClass를 통해로드됩니다. }} if (resolve) {resolveClass (c)} return c;}위의 코드에서는 Loadclass의 상위 대의원 메커니즘이 어떻게 작동하는지 명확하게 확인하기 위해 의견을 추가했습니다. 여기서 주목해야 할 한 가지는 공개 클래스 <?>로드 클래스 (문자열 이름)가 ClassNotFoundException이 최종적으로 표시되지 않으므로이 메소드를 무시할 수 있음을 의미합니다. 즉, 부모 위임 메커니즘이 깨질 수 있음을 의미합니다. 또한 위의 FindClass 메소드가 있음을 알았습니다.
2. indclass
우리는 java.lang.classloader의 소스 코드를 확인하고 FindClass의 구현은 다음과 같습니다.
보호 클래스 <?> findClass (문자열 이름) 던지기 classNotFoundException {새 ClassNotFoundException (name);}이 메소드의 기본 구현은 직접 예외를 제외하는 것임을 알 수 있지만 실제로이 방법은 응용 프로그램에 맡겨져 재정의합니다. 구현은 구현 로직에 따라 다릅니다. 나중에 정의를 설명해 봅시다. 자, 위의 분석을 통해 다음과 같은 결론을 도출 할 수 있습니다.
우리가 자신의 클래스 로더를 작성할 때, 부모 대의원 메커니즘을 따르고 싶다면 FindClass를 무시하면됩니다.
3. 정의
먼저 정의의 소스 코드를 살펴 보겠습니다.
정의
보호 된 최종 클래스 <?> defineClass (문자열 이름, 바이트 [] b, int off, int len)는 classformaterror {return defuleclass (name, b, off, len, null);} 던지기위의 코드 에서이 방법은 최종으로 정의되어 있습니다.이 방법은 실제로 JVM이 남은 항목입니다 파일은 Java Virtual Machine 사양에 의해 지정된 클래스의 정의를 준수해야합니다. 이 방법은 마침내 기본 방법을 호출하여 실제 클래스의로드를 구현합니다.
자, 위의 설명을 통해 다음 질문에 대해 생각해 봅시다.
우리가 java.lang.string 클래스를 스스로 썼다면 JDK 자체라고하는 클래스를 대체 할 수 있습니까?
대답은 아니오입니다. 우리는 그것을 달성 할 수 없습니다. 왜? 부모 대의원 메커니즘 이이 문제를 해결한다는 많은 온라인 설명이 보이지만 실제로는 정확하지 않습니다. 상위 대표단 메커니즘이 파손될 수 있으므로 클래스 로더를 작성하여 java.lang.string 클래스를로드 할 수 있지만, 특히 Java로 시작하는 클래스를위한 것이기 때문에 성공적으로로드되지 않을 것임을 알 수 있습니다.*,. JVM 구현은 Bootstrp에 의해로드되어야합니다.
"부모 위임 메커니즘"을 따르지 않는 시나리오
상기는 부모 대의원 메커니즘이 주로 다른 클래스 로더간에로드 된 클래스의 상호 작용 문제를 실현하기 위해 모료 로더에 전달되지만 실제로로드 된 클래스가 필요합니다. Java의 부모 클래스 로더. 이 상황의 발생에 대해 이야기합시다.
JAVA에는 JDBC, JNDI 등과 같은 SPI 라이브러리를 사용하는 SPI (Service Provider Interface) 표준이 있습니다. 우리는 JDBC가 제 3자가 제공 한 드라이버가 필요하며 Driver Jar 패키지는 응용 프로그램 자체에 배치된다는 것을 알고 있습니다. ClassPath 및 JDBC의 API는 JDK의 제공의 일부이며 Bootstrp에 의해로드되었습니다. Java는 스레드 컨텍스트 클래스 로딩의 개념을 소개합니다 드라이버, 스레드의 컨텍스트 클래스 로더를 통해로드하는 것은 괜찮습니다.
또한보다 유연한 클래스 로더 OSGI 및 일부 Java 앱 서버를 구현하려면 부모 대의원 메커니즘도 중단됩니다.