はこのように、たとえば、現在実行中の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
それは、Javaになると、コードは次のようになります。
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
}
}
シェルスクリプトからjarファイルを実行している場合には元のプロセスを終了する前に子プロセスが終了するのを待たなければならないため、この解決策はJVMの2つのインスタンスを同時に実行するオーバーヘッドにつながります。スクリプトから実行する可能性を提供する必要がない場合は、p.waitFor(12, TimeUnit.HOURS);
をp.waitFor(12, TimeUnit.MILLISECONDS);
に置き換えるか、おそらくすべてを削除しています(私はそれを試していません)ので、JVMのインスタンスを1つだけ持つことができます通常のJavaプログラムで実行します。
text
ウィジェットとscrollbar
での作業スニペットはhttp://ideone.com/eRjePQ
おかげであります!これまでにやったことですが、まだ優雅なソリューションを探しています。 –
@ m.vokhmもしそうなら、ここに戻って答えとして投稿してください。 – Baz
申し訳ありませんが、1)私の質問の正確な答え(私はプログラム的な方法について尋ねました)と2)まだ誰かが別の解決法を提案してくれることを願っているので、この回答を受け入れることはできません –