System.setProperty () 런타임에 클래스 경로를 변경할 수없는 이유는 무엇입니까?

StackOverflow https://stackoverflow.com/questions/271506

  •  06-07-2019
  •  | 
  •  

문제

나는 참조하고있다 의문 클래스 경로를 프로그래밍 방식으로 변경합니다.

나는 그 아래에 약간의 기능이 있음을 읽고 알았습니다. 체계 속성을 검색 한 다음 setProperties ()를 사용하여 설정할 수있는 getProperties로 클래스.

그러나 내가 얻은 대답은 그것이 작동하지 않는다는 것입니다. 나는 이것을 직접 시도하지 않았지만, 나는 전화를 받고있다.

명확히하기 위해, 이러한 setProperty () 및 getProperty () 메소드가 런타임에 변경할 수없는 경우 왜 아니면 이것은 클래스 경로 속성에만 해당됩니까?

누군가가 정말로 도움이되는 시나리오를 제시 할 수 있다면 감사하겠습니다.

도움이 되었습니까?

해결책

언제라도 원하는 시스템 속성을 확실히 설정할 수 있습니다. 문제는 효과가 있습니까? ClassPath의 경우 답은 아니오입니다. 시스템 클래스 로더는 시작 시퀀스의 초기 시점에서 초기화됩니다. ClassPath를 자체 데이터 구조로 복사하고 ClassPath 속성은 다시 읽지 않습니다. 변화는 시스템에서 아무런 영향을 미치지 않습니다.

그 이유는 두 가지가 될 수 있습니다. 더 적은 이유는 성능입니다. 빠른 리소스 조회를 위해 일종의 데이터 구조를 구축해야 할 수도 있고 매번 클래스 경로를 다시 표시하는 것은 비효율적 일 수 있습니다. 더 중요한 이유는 보안입니다. 당신은 도적 클래스가 당신 아래에 클래스 경로를 변경하고 다른 클래스의 손상된 버전을로드하기를 원하지 않습니다.

다른 팁

ClassPath를 수정하십시오

시스템 속성을 사용하여 클래스 경로를 설정할 수는 없지만 (JVM이 시스템 속성을 한 번 읽기 때문에 : 시작시) addURL 클래스 로더의 방법. 아래 솔루션은 현재 스레드를 고려하지 않습니다. 결과적으로 모든 상황에서는 정확하지 않을 수 있습니다.

예제 솔루션

다음 코드에 대한 Sun 웹 사이트의 원본 소스가 제거되었습니다.

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;                   

import java.io.File;
import java.io.IOException;

import java.net.URL;
import java.net.URLClassLoader;

/**
 * Allows programs to modify the classpath during runtime.              
 */                                                                     
public class ClassPathUpdater {                                         
  /** Used to find the method signature. */                             
  private static final Class[] PARAMETERS = new Class[]{ URL.class };   

  /** Class containing the private addURL method. */
  private static final Class<?> CLASS_LOADER = URLClassLoader.class;

  /**
   * Adds a new path to the classloader. If the given string points to a file,
   * then that file's parent file (i.e., directory) is used as the
   * directory to add to the classpath. If the given string represents a
   * directory, then the directory is directly added to the classpath.
   *
   * @param s The directory to add to the classpath (or a file, which
   * will relegate to its directory).
   */
  public static void add( String s )
    throws IOException, NoSuchMethodException, IllegalAccessException,
           InvocationTargetException {
    add( new File( s ) );
  }

  /**
   * Adds a new path to the classloader. If the given file object is
   * a file, then its parent file (i.e., directory) is used as the directory
   * to add to the classpath. If the given string represents a directory,
   * then the directory it represents is added.
   *
   * @param f The directory (or enclosing directory if a file) to add to the
   * classpath.
   */
  public static void add( File f )
    throws IOException, NoSuchMethodException, IllegalAccessException,
           InvocationTargetException {
    f = f.isDirectory() ? f : f.getParentFile();
    add( f.toURI().toURL() );
  }

  /**
   * Adds a new path to the classloader. The class must point to a directory,
   * not a file.
   *
   * @param url The path to include when searching the classpath.
   */
  public static void add( URL url )
    throws IOException, NoSuchMethodException, IllegalAccessException,
           InvocationTargetException {
    Method method = CLASS_LOADER.getDeclaredMethod( "addURL", PARAMETERS );
    method.setAccessible( true );
    method.invoke( getClassLoader(), new Object[]{ url } );
  }

  private static URLClassLoader getClassLoader() {
    return (URLClassLoader)ClassLoader.getSystemClassLoader();
  }
}

링크는 더 이상 작동하지 않습니다. http://forums.sun.com/thread.jspa?threadid=300557

예제 사용

다음 예제가 추가됩니다 /home/user/dev/java/app/build/com/package 런타임에 클래스 경로에 :

try {
  ClassPathUpdater.add( "/home/user/dev/java/app/build/com/package/Filename.class" );
}
catch( Exception e ) {
  e.printStackTrace();
}

System.SetProperty는 프로그램 시작시 보안 또는 프로토콜 핸들러를 설정하는 데 사용될 수 있습니다. 처럼:

/*
Add the URL handler to the handler property. This informs 
IBMJSSE what URL handler to use to handle the safkeyring 
support. In this case IBMJCE.
*/
System.setProperty("java.protocol.handler.pkgs", "com.ibm.crypto.provider");

또는 SSL 사용:

System.setProperty("javax.net.ssl.keyStore", context.getRealPath(KEYSTORE));
System.setProperty("javax.net.ssl.keyStorePassword", "password");
System.setProperty("javax.net.ssl.trustStore", context.getRealPath(TRUSTSTORE));
System.setProperty("javax.net.debug", "ssl");
HttpClient httpClient = new HttpClient();
GetMethod httpGet = new GetMethod("https://something.com");
httpClient.executeMethod(httpGet);
return new String(httpGet.getResponseBody());

그러나 그것 때문에 조심하십시오 런타임에 환경이 변경됩니다 모두 동일한 JVM에서 실행되는 응용 프로그램.
예를 들어 한 응용 프로그램이 Saxon과 다른 응용 프로그램을 Xalan과 함께 실행하고 System을 사용하여 변압기를 설정하려면 문제가 발생하면 문제가 발생합니다.

말했듯이 모니터링 된 System.SetProperty 기사,
System.setProperty ()는 사악한 호출 일 수 있습니다.

  • 100% 스레드 harsile입니다
  • 슈퍼 글로벌 변수가 포함되어 있습니다
  • 이러한 변수가 런타임에 신비하게 변경되면 디버그하기가 매우 어렵습니다.

ClassPath 속성과 관련하여 나는 이전 질문에서 말했다, 런타임으로 쉽게 변경할 수 없습니다.

특히 Java System Property java.class.path는 JRE가 인스턴스화 될 때 링크 된 링크를 작성하는 데 사용됩니다. 다시 읽지 않습니다. 따라서 속성에 대한 변경 사항은 실제로 기존 가상 머신에 아무것도하지 않습니다.

런타임에서 java.library.path를 변경하는 방법도 있습니다.

System.setProperty( "java.library.path", newPath);
Field fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths");
fieldSysPath.setAccessible(true);
fieldSysPath.set(null, null); // that's the key.

클래스 로더 클래스 의이 개인 정적 필드가 NULL로 설정되면 다음에 기본 라이브러리 클래스 로더를로드하려는 시도는 Java.library.path의 새로운 값을 사용하여 다시 초기화됩니다.

기본 아이디어 getProperty() 프로그램/코드는 JVM 외부에서 구성 할 수 있으며, java -Dfoo=bar 통사론.

명령 줄을 제어 할 수없는 상황에서 다른 소프트웨어 구성 요소 (예 : 로깅 구성 요소)에서 특정 동작을 구성 할 수 있으므로 서블릿 컨테이너에 배포되는 것을 생각하십시오. setProperty() 로깅 유틸리티를 인스턴스화하기 전에 프로그래밍 방식으로 설정을 교체하는 편리한 방법으로 제공됩니다.

The가 보여준 문제 classpath 문제는 프로그램이 일반적으로 처음 초기화 될 때 이러한 시스템 속성 만 정확히 한 번만 읽는다는 것입니다. 따라서 JVM 스타트 업 이후 클래스 경로를 변경하면 JVM이 이미 초기화되었고 이미 로거 인스턴스 (또는 무엇이든)를 얻은 후 일부 로깅 구성을 변경하기 때문에 앱 자체가 변경되지 않습니다. .

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top