이 같은 예를 들어, 현재 실행중인 VM에 대한 환경 변수를 설정하는 방법이 존재합니다 :
는
private static void setEnv(Map<String, String> newEnv) throws Exception {
Map<String, String> env = System.getenv();
Class<?> cl = env.getClass();
Field field = cl.getDeclaredField("m");
field.setAccessible(true);
@SuppressWarnings("unchecked")
Map<String, String> envMap = (Map<String, String>) field.get(env);
envMap.putAll(newEnv);
}
(아이디어는 답변에서 가져온 것입니다 이런 식으로 뭔가 트릭을 할해야 How do I set environment variables from Java?)
그러나 내 경우에는 VM 외부에서 실행되는 라이브러리에 영향을주기 위해 env vars가 필요하므로이 방법으로 내 문제가 해결되지 않습니다.
조금 생각한 후에 JVM의 부모 프로세스에 환경을 설정하고자한다는 것을 알았 기 때문에 먼저 필요한 변수를 설정 한 다음 내 앱을 실행할 다른 JVM 인스턴스를 다시 실행해야합니다. 변수가 VM 외부에서 실행 되더라도 라이브러리에 영향을줍니다.
그래서 논리는 다음과 같이해야합니다 다음은 자바에 오면
if (required vars are absent) {
start a process that {
set required vars;
run another instance of the JVM with the application inside;
}
exit;
}
// here the vars already set
do whatever we need in the proper environment
코드는 다음과 같이 보일 수 있습니다 :
public class SecondVM {
public static void main(String[] args) {
if ( System.getenv("SWT_GTK3") == null
|| System.getenv("LIBOVERLAY_SCROLLBAR") == null)
{
URL classResource = SecondVM.class.getResource("SecondVM.class");
boolean fromJar = classResource.getProtocol().equals("rsrc");
String exePath = ClassLoader.getSystemClassLoader().getResource(".").getPath();
exePath = new File(exePath).getAbsolutePath().replaceFirst("\\.$", "").replaceFirst("bin$", "");
if (!exePath.endsWith(System.getProperty("file.separator")))
exePath += System.getProperty("file.separator");
String[] script = {
"/bin/bash", "-c",
"export SWT_GTK3=0; "
+ "export LIBOVERLAY_SCROLLBAR=0; "
+ (fromJar? // TODO: Put the proper paths, packages and class names here
"java -jar " + exePath + "SecondVM.jar" : // if runs from jar
"java -cp ./bin/:../ExtLibs/swt_linux64/swt.jar " // if runs from under Eclipse or somewhat alike
+ "com.m_v.test.SecondVM")
};
try {
Process p = new ProcessBuilder(script).start();
// When jar is run from a bash script, it kills the second VM when exits.
// Let it has some time to take a breath
p.waitFor(12, TimeUnit.HOURS);
} catch (Exception e) { e.printStackTrace(); }
System.exit(0);
}
// Now the env vars are OK. We can use SWT with normal scrollbars
Display display = Display.getDefault();
// .... do watever we need
}
}
을 경우 쉘 스크립트에서 항아리를 실행하는 , 원래 프로세스를 종료하기 전에 하위 프로세스가 완료 될 때까지 기다려야하므로이 솔루션은 두 개의 JVM 인스턴스를 동시에 실행하는 오버 헤드를 초래합니다. 스크립트에서 실행할 수있는 가능성을 제공 할 필요가 없다면 p.waitFor(12, TimeUnit.HOURS);
은 p.waitFor(12, TimeUnit.MILLISECONDS);
으로 대체되거나 (아마도 테스트하지 않은 상태에서) 전혀 제거하지 않았을 수 있습니다. 따라서 JVM 인스턴스를 하나만 가질 수 있습니다 일반적인 자바 프로그램으로
작업 text
위젯 조각과 scrollbar
은 http://ideone.com/eRjePQ
감사에있다! 그게 지금까지 내가 한 일이지만 아직 좀 더 우아한 해결책을 찾기를 희망합니다. –
@ m.vokhm 글쎄, 만약 당신이, 돌아와서 여기에 답변으로 게시하시기 바랍니다. – Baz
죄송합니다. 1) 내 질문에 대한 정확한 대답이 아니기 때문에 (프로그래밍 방식에 대해 질문했습니다.) 2) 다른 사람이 다른 해결책을 제안하기를 바랍니다. –