자바 사용자 정의 클래스 로 더 기반 열 배치 프로 세 스 분석
열 배 치 는 응용 프로그램 을 다시 시작 하지 않 은 상태 에서 클래스 의 정의 인 바이트 코드 파일 이 수정 되면 이 Class 가 만 든 대상 을 교체 할 수 있 습 니 다.일반적으로 클래스 의 로 딩 은 시스템 이 자체 적 으로 가지 고 있 는 클래스 로 딩 기 에 의 해 이 루어 지 며,같은 전체 이름 의 자바 류 에 대해 서 는 한 번 만 불 러 올 수 있 으 며,마 운 트 해제 할 수 없습니다.사용자 정의 ClassLoader 를 사용 하여 시스템 의 로 더 를 교체 할 수 있 습 니 다.새로운 ClassLoader 를 만 들 고 클 라 스 를 불 러 올 수 있 습 니 다.클 라 스 대상 은 새로운 것 입 니 다.(같은 종류의 로 더 가 아니 기 때 문 입 니 다)이 클 라 스 대상 으로 인 스 턴 스 를 만 들 고 동적 으로 새로운 것 을 실현 합 니 다.예 를 들 어 JSP 파일 을 수정 하면 효력 이 발생 합 니 다.사용자 정의 ClassLoader 를 이용 하여 이 루어 집 니 다.
데 몬 스 레 드 를 만 들 고 클 라 스 파일 이 수정 되 었 는 지 계속 확인 하 며 파일 의 마지막 수정 시간 을 판단 해 야 합 니 다.
프레젠테이션:
원래 프로그램:
수정 후 다시 컴 파일:
코드:
package Dynamic;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.concurrent.TimeUnit;
public class ClassLoadStudy {
public static void main(String[] args) throws Exception {
HotDeploy hot = new HotDeploy("Dynamic.Task");
hot.monitor();
while (true) {
TimeUnit.SECONDS.sleep(2);
hot.getTask().run();
}
}
}
//
class HotDeploy {
private static volatile Runnable instance;
private final String FILE_NAME;
private final String CLASS_NAME;
public HotDeploy(String name) {
CLASS_NAME = name; //
name = name.replaceAll("\\.", "/") + ".class";
FILE_NAME = (getClass().getResource("/") + name).substring(6); // class ,substring(6) file:/
}
//
public Runnable getTask() {
if (instance == null) { // , ,
synchronized (HotDeploy.class) {
if (instance == null) {
try {
instance = createTask();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
return instance;
}
// , class
private Runnable createTask() {
try {
Class clazz = MyClassLoader.getLoader().loadClass(CLASS_NAME);
if (clazz != null)
return (Runnable)clazz.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
// , class , ,
public void monitor() throws IOException {
Thread t = new Thread(()->{
try {
long lastModified = Files.getLastModifiedTime(Path.of(FILE_NAME)).toMillis();
while(true) {
Thread.sleep(500);
long now = Files.getLastModifiedTime(Path.of(FILE_NAME)).toMillis();
if(now != lastModified) { // class
lastModified = now;
instance = createTask(); //
}
}
} catch (InterruptedException | IOException e) {
e.printStackTrace();
}
});
t.setDaemon(true); //
t.start();
}
}
//
class MyClassLoader extends ClassLoader {
@Override
public Class<?> findClass(String name) throws ClassNotFoundException {
try {
String fileName = "/" + name.replaceAll("\\.", "/") + ".class";
InputStream is = getClass().getResourceAsStream(fileName);
byte[] b = is.readAllBytes();
return defineClass(name, b, 0, b.length);
} catch (IOException e) {
throw new ClassNotFoundException(name);
}
}
public static MyClassLoader getLoader() {
return new MyClassLoader();
}
}
만난 구덩이:처음에는 클래스 로 더 를 사용자 정의 할 때 loadClass(String name)방법 을 다시 썼 으 나 오류 가 계속 발생 했 습 니 다.나중에 알 게 되 었 습 니 다.Task 류 가 자바.lang.Runnable 인 터 페 이 스 를 실현 하고 loadClass 를 다시 쓰 는 방법 은 부모 위임 체 제 를 파괴 하여 사용자 정의 클래스 로 더 를 자바.lang.Runnable 로 불 러 왔 으 나 자바 보안 체제 에 의 해 금지 되 어 오류 가 발생 했 습 니 다.defineClass 는 preDefineClass 를 호출 합 니 다.preDefineClass 는 패키지 이름 을 검사 합 니 다.자바 로 시작 하면 이상 을 던 집 니 다.사용자 정의 클래스 로 더 를 불 러 와 자바 자체 라 이브 러 리 를 불 러 오 는 것 이 혼 란 스 럽 기 때 문 입 니 다.
그래서 findClass 방법 을 다시 썼 지만 안 됩 니 다.findClass 방법 은 항상 실행 되 지 않 습 니 다.컴 파일 된 클래스 는 classpath 에 있 기 때 문 입 니 다.사용자 정의 ClassLoader 의 부모 로 더 는 AppClassLoader 입 니 다.부모 위임 체제 로 인해 클래스 는 Application ClassLoader 에 의 해 불 러 옵 니 다.따라서 사용자 정의 findClass 방법 은 실행 되 지 않 습 니 다.해결 방법 은 구조 기 ClassLoader(ClassLoader parent)에 null 을 전송 하거나 getSystem ClassLoader().getParent()를 전송 하 는 것 입 니 다.
그리고 경로 문제:
4.567917.path 가/로 시작 하지 않 을 때 기본 값 은 이러한 가방 에서 자원 을 가 져 옵 니 다.path 가/로 시작 할 때 ClassPath 루트 에서 가 져 옵 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JPA + QueryDSL 계층형 댓글, 대댓글 구현(2)이번엔 전편에 이어서 계층형 댓글, 대댓글을 다시 리팩토링해볼 예정이다. 이전 게시글에서는 계층형 댓글, 대댓글을 구현은 되었지만 N+1 문제가 있었다. 이번에는 그 N+1 문제를 해결해 볼 것이다. 위의 로직은 이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.