소스 코드 분석 자바 클래스 로 더
4.567917.자바 가상 머 신(JVM 고급 특성 과 최 적 실천)을 깊이 이해 하 는 주지 명 선생님
3 층 류 의 적재 기,부모 위임 체제 에 대해 본 고 는 더 이상 판 서 를 하지 않 고 독자 가 스스로 바 이 두 를 할 수 있다.
그렇다면 JDK 의 소스 코드 에서 3 층 구조의 구체 적 인 실현 은 어 떨 까?
Bootstrap ClassLoader(유도 클래스 로 더)
유도 클래스 로 더 는 C++로 이 루어 집 니 다.자바 코드 가 아 닙 니 다.따라서 자바 코드 에 서 는 이러한 로 더 를 가 져 올 수 없습니다.
일반적으로 클래스 로 더 는 네 가지(유도 류,확장 류,시스템 류 및 사용자 정의 클래스 로 더)로 나 뉘 지만,사실은 JVM 가상 컴퓨터 규범 에서 지원 하 는 두 가지 유형의 로 더 는 유도 클래스 로 더(Bootstrap ClassLoader)와 자체 정의 클래스 로 더(User-Defined ClassLoader)로 나 뉜 다.따라서 확장 클래스 와 시스템 클래스 를 사용자 정의 클래스 로 통칭 할 수 있다.
Extension ClassLoader(확장 클래스 로 더)와 Appclass Loader(시스템 클래스 로 더)
확장 클래스 로 더 와 시스템 클래스 로 더 는 자바 언어 로 작 성 됩 니 다.sum.misc.Launcher 의 두 내부 클래스 ExtClassLoader 와 AppClassLoader 로 구체 적 으로 실 현 됩 니 다.LaunchLacher 클래스 에 들 어가 보 겠 습 니 다.(이 종 류 는 Oacle jdk 에서 원본 코드 를 공개 하지 않 았 습 니 다.구체 적 인 소스 코드 를 볼 필요 가 있 는 독 자 는 open jdk 를 다운로드 하여 구체 적 인 소스 코드 를 볼 수 있 습 니 다.필 자 는 IDEA 역 컴 파일 후 생 성 된 코드 만 사용 하여 분석 합 니 다).
우선 Laucncher 의 구조 방법:
public Launcher() {
Launcher.ExtClassLoader var1;
try {
//
var1 = Launcher.ExtClassLoader.getExtClassLoader();
} catch (IOException var10) {
throw new InternalError("Could not create extension class loader", var10);
}
try {
//
this.loader = Launcher.AppClassLoader.getAppClassLoader(var1);
} catch (IOException var9) {
throw new InternalError("Could not create application class loader", var9);
}
//
Thread.currentThread().setContextClassLoader(this.loader);
String var2 = System.getProperty("java.security.manager");
if (var2 != null) {
SecurityManager var3 = null;
if (!"".equals(var2) && !"default".equals(var2)) {
try {
var3 = (SecurityManager)this.loader.loadClass(var2).newInstance();
} catch (IllegalAccessException var5) {
} catch (InstantiationException var6) {
} catch (ClassNotFoundException var7) {
} catch (ClassCastException var8) {
}
} else {
var3 = new SecurityManager();
}
if (var3 == null) {
throw new InternalError("Could not create SecurityManager: " + var2);
}
System.setSecurityManager(var3);
}
}
Launcher 의 구조 방법 에서 Launcher.ExtClassLoader 형식의 부분 변수 var 1(여 기 는 역 컴 파일 된 변수 이름)을 정의 하고 Launcher.ExtClassLoader.getExtClassLoader()방법 으로 이 부분 변수 에 값 을 부여 하고 Launcher.AppClassLoader.getAppClassLoader(var 1)를 호출 하 는 것 을 볼 수 있 습 니 다.인 스 턴 스 변수(유형 은 Launcher.AppClassLoader)에 값 을 부여 합 니 다.시스템 클래스 에 값 을 부여 할 때 확장 클래스 로 더 를 매개 변수 로 전송 하 는 것 을 주의해 야 합 니 다.또한 구조 방법 에서 시스템 클래스 로 더 를 현재 스 레 드 의 컨 텍스트 클래스 로 설정 합 니 다.컨 텍스트 클래스 로 더 에 대해 서 는 기본 형식 으로 사용자 코드 를 호출 할 때 방법 부모 클래스 로 더 구역 에서 하위 클래스 로 더 를 요청 하여 클래스 로 더 를 완성 하 는 행위 입 니 다.주로 JDBC,JNDI 등 SPI 서비스 제공 자 인터페이스 에 사용 되 어야 합 니 다.여 기 는 자세히 전개 되 지 않 습 니 다.
상기 소스 코드 중의**getExtClassLoader()와 getAppClassLoader()*방법 소스 코드 는 다음 과 같 습 니 다.
getExtClassLoader()는 Launcher 의 내부 클래스 ExtClassLoader(확장 클래스 로 더)의 정적 방법 입 니 다.
// ExtClassLoader
private static volatile Launcher.ExtClassLoader instance;//
public static Launcher.ExtClassLoader getExtClassLoader() throws IOException {
// ,ExtClassLoader double-checking
if (instance == null) {
Class var0 = Launcher.ExtClassLoader.class;
synchronized(Launcher.ExtClassLoader.class) {
if (instance == null) {
instance = createExtClassLoader(); // ExtClassLoader
}
}
}
return instance;
}
// createExtClassLoader()
private static Launcher.ExtClassLoader createExtClassLoader() throws IOException {
try {
return (Launcher.ExtClassLoader)AccessController.doPrivileged(new PrivilegedExceptionAction<Launcher.ExtClassLoader>() {
public Launcher.ExtClassLoader run() throws IOException {
File[] var1 = Launcher.ExtClassLoader.getExtDirs();
int var2 = var1.length;
for(int var3 = 0; var3 < var2; ++var3) {
MetaIndex.registerDirectory(var1[var3]);
}
return new Launcher.ExtClassLoader(var1); //
}
});
} catch (PrivilegedActionException var1) {
throw (IOException)var1.getException();
}
}
// ExtClassLoader
public ExtClassLoader(File[] var1) throws IOException {
// !!,
super(getExtURLs(var1), (ClassLoader)null, Launcher.factory);
SharedSecrets.getJavaNetAccess().getURLClassPath(this).initLookupCache(this);
}
// URLClassLoader
// , ExtClassLoader
public URLClassLoader(URL[] urls, ClassLoader parent, getParent() null
URLStreamHandlerFactory factory) {
super(parent);
// this is to make the stack depth consistent with 1.1
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkCreateClassLoader();
}
acc = AccessController.getContext();
ucp = new URLClassPath(urls, factory, acc);
}
getAppClassLoader()는 Launcher 의 내부 클래스 AppClassLoader(시스템 클래스 로 더)의 정적 방법 입 니 다.
public static ClassLoader getAppClassLoader(final ClassLoader var0) throws IOException {
final String var1 = System.getProperty("java.class.path");
final File[] var2 = var1 == null ? new File[0] : Launcher.getClassPath(var1);
return (ClassLoader)AccessController.doPrivileged(new PrivilegedAction<Launcher.AppClassLoader>() {
public Launcher.AppClassLoader run() {
URL[] var1x = var1 == null ? new URL[0] : Launcher.pathToURLs(var2);
return new Launcher.AppClassLoader(var1x, var0); // ,
}
});
}
// AppClassLoader
AppClassLoader(URL[] var1, ClassLoader var2) {
// var2 getAppClassLoader() var0, var0 Launcher ExtClassLoader
// ExtClassLoader , var2 , AppClassLoader ExtClassLoader
super(var1, var2, Launcher.factory);
this.ucp.initLookupCache(this);
}
상기 두 가지 방법 을 통 해 확장 클래스 로 더 를 가 져 올 때 null(즉 유도 로 더)이 고 같은 종류의 로 더 는 계승(Inheritance)관계 인 것 처럼 보이 지만 실제로는 관 계 를 포함 하 는 지 설명 할 수 있다.하층부 캐리어 에는 상층 부 캐리어 의 인용 이 포함 되 어 있다.ClassLoader 추상 클래스
상기 한 ExtClassLoader 와 AppClassLoader 는 모두 ClassLoader 류 에 계승 되 었 고 ClassLoader 추상 류 도 로드 체제 의 초석 이다.그 다음 에 우 리 는 이 유형 에 들 어가 서 그의 주요 방법 을 살 펴 보 자.
public final classLoader getParent()
이러한 종류의 로 더 를 되 돌려 주 는 슈퍼 클래스 로 더
public Classloadclass(String name) throws ClassNotFoundException
이름 이 name 인 클래스 를 불 러 오고 결 과 를 java.lang.Class 클래스 로 되 돌려 줍 니 다.클래스 를 찾 지 못 하면 ClassNotFoundException 이상 으로 돌아 갑 니 다.이 방법의 논 리 는 양친 위임 모델 의 실현 이다.
protected class findClass(string name)throws ClassNotFoundException
4
protected final Class defineClass(String name, byte[] b, int off,int len)
4.567917.주어진 바이트 배열 b 에서 Class 로 전환 하 는 인 스 턴 스 에 따라 off 와 len 매개 변 수 는 실제 Class 정보 가 by te 배열 에서 의 위치 와 길 이 를 나타 내 는데 그 중에서 by te 배열 b 는 ClassLoader 가 외부 에서 가 져 온 것 입 니 다.이것 은 보 호 받 는 방법 입 니 다.사용자 정의 ClassLoader 하위 클래스 에서 만 사용 할 수 있 습 니 다
4.567917.링크 가 지정 한 자바 클래스 입 니 다.이 방법 을 사용 하면 클래스 의 Class 대상 을 만 드 는 동시에 해석 할 수 있 습 니 다.앞에서 말 했 듯 이 링크 단 계 는 주로 바이트 코드 를 검증 하고 클래스 변수 에 메모 리 를 할당 하 며 초기 값 을 설정 하 는 동시에 바이트 코드 파일 의 기호 인용 을 직접 참조 로 변환 합 니 다protected final Class findLoadedClass(String name)
4.567917.이것 도 ClassLoader 의 인 스 턴 스 입 니 다.이 필드 에 표 시 된 ClassLoader 는 이 ClassLoader 의 부모 라 고도 부 릅 니 다.클래스 를 불 러 오 는 과정 에서 classLoader 는 일부 요청 을 부모 에 게 맡 길 수 있 습 니 다이러한 방법 에 대해 서 는 일일이 펼 치지 않 고 주로 loadclass()와 findClass()를 살 펴 봅 니 다.
loadClass()
public Class<?> loadClass(String name) throws ClassNotFoundException {
// loadClass loadClass, , false
return loadClass(name, false);
}
// loadClass
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException{// resolve:true-> class
synchronized (getClassLoadingLock(name)) {// ,
//
Class<?> c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
// , 。
try {
//
if (parent != null) {
// , loadClass ( )
c = parent.loadClass(name, false);
} else {
// parent == null:
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
// or
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;
}
}
findClass()
// ClassLoader findClass()
rotected Class<?> findClass(String name) throws ClassNotFoundException {
throw new ClassNotFoundException(name);
}
ClassLoader 에서 findCLass()방법 이 이상 을 직접 던 지 는 것 을 볼 수 있 기 때문에 구체 적 인 실현 은 하위 클래스 에서 재 작성 하여 이 루어 진 것 입 니 다.ClassLoader 의 하위 클래스 SecureClassLoader 의 하위 클래스 URLClassLoader 에서 이 방법 을 다시 썼 습 니 다.URLClassLoader 의 findCLass()방법
protected Class<?> findClass(final String name)
throws ClassNotFoundException
{
final Class<?> result;
try {
result = AccessController.doPrivileged(
new PrivilegedExceptionAction<Class<?>>() {
public Class<?> run() throws ClassNotFoundException {
String path = name.replace('.', '/').concat(".class");//
Resource res = ucp.getResource(path, false);// class
if (res != null) {
try {
// defineClass() Class ,
// defineClass() class Class
return defineClass(name, res);
} catch (IOException e) {
throw new ClassNotFoundException(name, e);
}
} else {
return null;
}
}
}, acc);
} catch (java.security.PrivilegedActionException pae) {
throw (ClassNotFoundException) pae.getException();
}
if (result == null) {
throw new ClassNotFoundException(name);
}
return result;
}
마지막 으로 배열 류 로 딩 에 대한 세부 사항 을 추가 합 니 다.그룹 클래스 의 Class 대상 은 클래스 로 더 가 만 든 것 이 아니 라 자바 실행 기 JVM 에서 필요 에 따라 자동 으로 만 듭 니 다.배열 류 의 클래스 로 더 에 있어 서 는 Class.getClassLoader()를 통 해 되 돌아 갑 니 다.배열 에 있 는 요소 형식의 클래스 로 더 와 같 습 니 다.배열 에 있 는 요소 형식 이 기본 데이터 형식 이 라면 배열 류 는 클래스 로 더 가 없습니다.
자바 류 로 더 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 자바 류 로 더 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 시기 바 랍 니 다.앞으로 많은 응원 바 랍 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Is Eclipse IDE dying?In 2014 the Eclipse IDE is the leading development environment for Java with a market share of approximately 65%. but ac...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.