Java와 다른 언어의 차이점은 Java는 JVM(Java Virtual Machine)에서 실행된다는 점입니다. 이는 컴파일된 코드가 특정 시스템에서 실행되는 형식이 아닌 플랫폼 독립적인 형식으로 저장된다는 의미입니다. 이 형식은 기존의 실행 가능한 코드 형식과 많은 중요한 차이점이 있습니다. 특히 C 또는 C++ 프로그램과 달리 Java 프로그램은 독립적인 실행 파일이 아니지만 각 클래스 파일은 Java 클래스에 해당하는 여러 개별 클래스 파일로 구성됩니다. 또한 이러한 클래스 파일은 즉시 메모리에 로드되지 않고 프로그램에서 필요할 때 로드됩니다. 클래스 로더는 Java 가상 머신에서 클래스를 메모리에 로드하는 데 사용되는 도구입니다. 또한 Java 클래스 로더도 Java로 구현됩니다. 이렇게 하면 Java 가상 머신에 대한 심층적인 이해 없이도 자신만의 클래스 로더를 쉽게 만들 수 있습니다.
클래스 로더를 만드는 이유는 무엇입니까?
이제 Java 가상 머신에는 클래스 로더가 있으므로 다른 클래스 로더를 직접 만들어야 합니까? 좋은 질문입니다. 기본 클래스 로더는 로컬 시스템에서 클래스를 로드하는 방법만 알고 있습니다. 프로그램이 완전히 기본적으로 컴파일되면 기본 클래스 로더가 일반적으로 잘 작동합니다. 그러나 Java의 가장 흥미로운 점 중 하나는 로컬이 아닌 네트워크에서 클래스를 로드하는 것이 얼마나 쉬운지입니다.
예를 들어 브라우저는 사용자 정의 클래스 로더를 통해 클래스를 로드할 수 있습니다. 클래스를 로드하는 방법도 다양합니다. Java의 가장 흥미로운 점 중 하나는 로컬이나 네트워크에서 간단하게 사용자 정의할 수 있다는 것입니다.
* 신뢰할 수 없는 코드를 실행하기 전에 자동으로 디지털 서명을 확인합니다.
* 사용자가 제공한 비밀번호를 기반으로 코드를 해독합니다.
* 사용자 요구에 따라 클래스를 동적으로 생성합니다. JDK(Java Software Development Kit) 애플릿뷰어(소형 애플리케이션 브라우저) 또는 기타를 사용한 경우 사용자 정의 클래스 로더의 예는 관심 있는 모든 것을 애플리케이션에 쉽게 통합할 수 있습니다.
Java 임베디드 브라우저의 경우 이미 사용자 정의 클래스 로더를 사용하고 있습니다. Sun이 처음 Java 언어를 출시했을 때 가장 흥미로웠던 것 중 하나는 Java가 원격 웹 사이트에서 다운로드한 코드를 어떻게 실행하는지 관찰하는 것이었습니다. HTTP를 통해 원격 사이트에서 실행
P 연결에 의해 전송된 바이트코드가 조금 이상해 보입니다. 이는 Java에 사용자 정의 클래스 로더를 설치할 수 있는 기능이 있기 때문에 작동합니다. 애플릿 브라우저에는 클래스 로더가 포함되어 있습니다. 이 클래스 로더는 로컬에서 Java 클래스를 찾는 대신 원격 서버에 액세스하여 HTTP를 통해 원본 바이트코드 파일을 로드한 다음 이를 Java 가상 머신에서 Java 클래스로 변환합니다. 물론 클래스 로더는 다른 많은 작업도 수행합니다. 즉, 안전하지 않은 Java 클래스를 차단하고 서로 다른 페이지에 있는 서로 다른 애플릿이 서로 간섭하지 않도록 합니다. Luke Gorrie가 작성한 패키지인 Echidna는 여러 Java 애플리케이션을 Java 가상 머신에서 안전하게 실행할 수 있는 개방형 Java 소프트웨어 패키지입니다. 이는 사용자 정의 클래스 로더를 사용하여 각 애플리케이션에 클래스 파일의 사본을 제공함으로써 애플리케이션 간의 간섭을 방지합니다.
자바 클래스 로더:
Java에는 기본적으로 부트스트랩 클래스 로더, 확장 클래스 로더 및 시스템 클래스 로더(애플리케이션 클래스 로더라고도 함)의 세 가지 클래스 로더가 있습니다.
클래스 로더는 Java의 가장 강력한 기능 중 하나입니다. 그러나 개발자는 종종 구성요소를 클래스로드하는 것을 잊어버립니다. 클래스 로더는 런타임 시 클래스 파일을 찾고 로드하는 일을 담당하는 클래스입니다. Java에서는 다양한 클래스 로더, 심지어 사용자 정의 클래스 로더를 사용할 수 있습니다.
Java 프로그램에는 각각 단일 Java 클래스에 해당하는 많은 클래스 파일이 포함되어 있습니다. 정적 C 프로그램과 달리 이러한 클래스 파일은 메모리에 한 번 로드되며 언제든지 로드해야 합니다. 이것이 클래스 로더를 다르게 만드는 이유입니다. 소스 파일(일반적으로 .class 또는 .jar 파일)에서 플랫폼 독립적인 바이트코드를 얻은 다음 해석하고 실행할 수 있도록 JVM 메모리 공간에 로드합니다. 기본적으로 애플리케이션의 각 클래스는 java.lang.ClassLoader에 의해 로드됩니다. 상속이 가능하기 때문에 자유롭게 기능을 강화할 수 있습니다.
커스텀 클래스 로더
import java.io.*;
java.net.* 가져오기;
import java.util.*;
import java.lang.reflect.Method;
공용 클래스 CustomClassLoader는 URLClassLoader를 확장합니다.
private FileInputStream 입력 = null //파일 입력 스트림;
private ByteArrayOutputStream out = null; //바이트 배열 출력 스트림
private String[] url = null; //클래스 파일 로딩 경로
private byte[] data = null; 클래스 파일 바이트코드
private String ExtensionalName = ""; //클래스 파일 확장자
공개 CustomClassLoader(URL[] urls)에서 예외가 발생함{
슈퍼(url);
this.url = 새로운 문자열[urls.length];
for (int i = 0; i < urls.length; i++) {
this.url[i] = urls[i].toURI().toString();
}
}
/*
* URL 분석
*/
개인 무효 setFilePath() {
for (int i = 0; i < this.url.length; i++) {
if (this.url[i].substring(0,4).toLowerCase().equals("file") == true) {
this.url[i] = this.url[i].substring(5);
}
}
}
/*
* 지정된 클래스 이름(패키지 이름 + 클래스 이름)을 가진 파일의 바이트코드를 얻습니다.
* @name 이름 문자열
* @return 바이트[]
*/
private byte[] getFileData(문자열 이름) {
노력하다 {
this.setFilePath();
for (문자열 URL : this.url) {
String fileName = url + name.replace('.', '/').concat(".") +
this.getExtensionalName();
input = new FileInputStream(새 파일(파일 이름));
if (입력 != null) {
부서지다;
}
}
출력 = 새로운 ByteArrayOutputStream();
데이터 = 새 바이트[1024];
int len = -1;
while ((len = input.read(data)) != -1) {
out.write(데이터, 0, len);
}
데이터 = out.toByteArray();
} 잡기(예외 e) {
e.printStackTrace();
} 마지막으로 {
노력하다 {
if (입력 != null)
입력.닫기();
if (out != null)
종료.닫기();
데이터를 반환합니다.
} 잡기(예외 e) {
e.printStackTrace();
null을 반환;
}
}
}
/*
* 지정된 클래스 이름을 기반으로 클래스 파일 검색
* @param 이름 문자열
* @return 클래스
*/
보호 클래스 findClassByName(문자열 이름) {
노력하다 {
byte[] 데이터 = this.getFileData(이름);
if (데이터 == null) {
null을 반환;
}
return this.defineClass(name, data, 0, data.length);
} 잡기(예외 e) {
e.printStackTrace();
null을 반환;
}
}
/*
* loadClass() 메서드 재정의
* @param 이름 문자열
* @return 클래스
*/
공개 클래스 loadClass(문자열 이름) {
클래스 c = null;
노력하다 {
c = super.loadClass(이름);
} 잡기(ClassNotFoundException e) {
e.printStackTrace();
} 마지막으로 {
if (c == null) //부모 클래스의 기본 메소드가 지정된 클래스에 로드되지 않은 경우 사용자 정의 메소드를 사용하여 찾습니다.
c = this.findClassByName(이름);
c를 반환;
}
}
공개 문자열 getExtensionalName() {
확장 이름을 반환합니다.
}
공공 무효 setExtensionalName(문자열 확장 이름) {
this.extensionalName = 확장명;
}
public static void main(String[] args)에서 예외가 발생합니다.
URL[] url = new URL[] {new URL("file:e:/")} //로드하려는 클래스에 경로를 추가합니다.
//네트워크 또는 로컬일 수 있음
CustomClassLoader csl = new CustomClassLoader(url);
csl.setExtensionalName("rs");
클래스 c1 = csl.loadClass("com.demo");
객체 obj = c1.newInstance();
메소드 method = c1.getMethod("printText", null);
method.invoke(obj, null);
}