Spring

Spring에서 클래스 경로로 하위 프로세스를 시작하면 ClassNotFoundException이 발생합니다.

기록만이살길 2021. 3. 9. 08:04
반응형

Spring에서 클래스 경로로 하위 프로세스를 시작하면 ClassNotFoundException이 발생합니다.

1. 질문(문제점):

Java의 internal을 통해 하위 프로세스에서 다른 클래스를 시작하는 응용 프로그램이 java.lang.ProcessHandler있습니다. 아주 간단합니다.

public MySubProcessHandler() {
        // setup commands
        String javaHome = System.getProperty(ProcessKeys.JAVA_HOME);
        String javaBin = Paths.get(javaHome, "bin", "java").toString();
        String classpath = System.getProperty(ProcessKeys.JAVA_CLASSPATH);
        String className = MyServer.class.getName();

        List<String> command = new LinkedList<>();
        command.add(javaBin);
        command.add("-classpath");
        command.add(classpath);
        command.add(className);

        // setup sub process
        ProcessBuilder processBuilder = new ProcessBuilder(command);
        processBuilder.start();
}

이제 모든 것이이 응용 프로그램과 IntelliJ에서 잘 작동합니다. 그러나 Spring-Boot 응용 프로그램에서도 이것을 사용합니다. 실행 가능한 JAR을 시작하고 하위 프로세스를 만들고 싶을 때 해당 하위 프로세스의 오류 스트림이 저에게 보냅니다.

Error: Could not find or load main class my.path.to.MyServer
Caused by: java.lang.ClassNotFoundException: my.path.to.MyServer

Spring 애플리케이션에서 실행 가능한 jar를 확인할 때 실제로 내부 프로젝트 클래스로만 구성되지만 의존성은 없습니다. 의존성은BOOT-INF/lib/my-server.jar

질문 : Spring이이 클래스를로드 MySubProcessHandler하여 찾을 수 있도록하려면 어떻게해야합니까?

My Current Approaches : 첫째, Spring이 클래스를로드하도록 강제하기 위해 설정 MyServer을 통해 이것을 해킹 할 수 있다고 생각했습니다 @Bean. 불행히도 작동하지 않는 것 같습니다. IntelliJ가 응용 프로그램을 시작할 때 클래스 경로에 종속 메이븐 리포지토리를 자동으로 추가하고 문제가 해결된다는 것을 알았습니다! 따라서 IntelliJ에서는 잘 작동합니다. 그러나 필요한 jar ( "누락 된"클래스 포함)가 이미 fat jar에 있다는 점을 고려하면 시작시 maven 의존성을 클래스 경로에 수동으로 추가하는 것은 잘못된 것 같습니다. 이것에 대한 또 다른 해결책이 있어야합니다.

2. 해결방안:

이미 지적했듯이 Spring은 다른 방법으로 시작하거나 (Spring에는 용어가 시작됨) 클래스를로드합니다. 이것은 " The Executable Jar Format "에 대한 Spring의 문서잘 설명되어 있습니다.

일반적으로 다음 명령을 통해 직접 기본 클래스를 시작할 수 있습니다.

java -cp my-project.jar my.path.to.MyServer

그러나 my-project.jarSpring에서 실행 가능한 JAR 인 경우 PropertiesLauncher로드 및 실행 을 위해 Spring을 사용해야 합니다. 다음을 통해이 작업을 수행 할 수 있습니다.

java -cp my-spring-project.jar \
   -Dload.main=my.path.to.MyServer \
   org.springframework.boot.loader.PropertiesLauncher

따라서 이것은 단순히 스프링 부트를 통해 JVM을 시작하고 Spring의 PropertiesLauncher. MySubProcessHandler()이 명령에 따라 위 의 코드를 업데이트하면 문제가 해결됩니다.

65706851
반응형