Javaでは、main()がコマンドラインパラメータを保存しなかった場合でも、コマンドラインパラメータを取得する方法はありますか?
-
21-08-2019 - |
質問
特定の CLP を解析する main() を含むプログラムがありますが、それらをどこにも保存しません。次に、元の CLP にアクセスする必要がある独自のプラグイン コードを作成します (そのため、より多くのパラメーターを送信できるようになります)。ただし、main()を変更することはできません
どうやらC#でこれを行う方法があることがわかりました, Linux 上で同等の Java ソリューションを探しています。
アップデート:明らかに、main() がどのように機能するかは知っています。残念ながら、既存のアプリケーションやその呼び出し方法を変更することはできません (CLP を除く)。サンドボックス化されたプラグイン コードを介してのみアクセスできます。私の質問は、JVM が呼び出されたコマンドライン (-D を指定した環境変数ではなく) を取得する方法があるかどうかです。
解決
ほかにも、その主なものだと思うのだけどオプションという幅広いステークホルダーの営業システムレベルの実行コマンドの引数になります。
Linuxにおけるセントロイド分分子動力学ライン引数オペレーティングシステムの過程で保存 /proc/pid/cmdline
でしまうのidです。こちらをご参照:
ですが、どのようなJavaプログラムの取得自己の処理ID"はどのようになりますか。
の活用により開 /proc/pid/cmdline を解析します。このファイルの形式とは、例cはこちら:
能があるのを包むこの二つの話を一つのシェルスクリプトを呼び出すからjava.
れますので、ご注意ください極めて不可搬型のベーシックモデルで、バランスhacky.が必要にな...
他のヒント
あなたはJavaのmainメソッドは、引数として文字列配列を取るだけで、別の静的メソッドであることを認識したら、解決策は簡単です。
CLPのを保存する新しいクラスを作成し、古いクラスを呼び出します。その後、あなたは新しいクラスを使用してCLPのにアクセスすることができます:
import NotToBeChangedMainClass;
public MyMainClass {
public static final String[] ARGUMENTS;
public static void main(String ... args) {
ARGUMENTS = args;
NotToBeChangedMainClass.main(args);
}
}
最後に、変更どんな外部の発信者(例えば、任意のバッチファイル)MyMainClassの代わりNotToBeChangedMainClassを使用します。あなたがrunable瓶または類似のものを使用している場合、これは適切な設定ファイルを変更する必要があります。
あなた自身のメインクラスを作成します。引数を保存します。古いmain
を呼び出します。
(メインクラス名またはSystem.getProperty
前に)コマンドラインで-Dkey=value
と-jar
を使用する方が簡単かもしれません。
選択肢がない場合は、既存のクラス名をすべて正確な名前で保持する必要があります (あなたのコメントに記載されているように 私の前の回答へ)、その場合は、AspectJ を使用する必要があります。
次のクラスがあると考えてみましょう。
public class UnmodifyableClassWithMain {
public static void main(String[] args) {
System.out.println("In main");
new ClassUsingArgumentRegistry();
}
}
まず、コマンドライン引数を保持するものが必要です。わかりやすくするために、静的フィールドを持つ単純なクラスを使用します。
public class ArgumentRegistry {
public static String[] ARGS;
}
次に、main への呼び出しをインターセプトして引数を保存するアスペクトを定義する必要があります。
public aspect StoreArgumentsOfMain {
/**
* This pointcut intercepts all calls to methods called main with a string array as
* argument.
*/
pointcut mainMethod(String[] arguments): execution(void main(String[])) && args(arguments);
/**
* Before the original main method gets called, store the arguments in the registry.
*/
before(String[] arguments): mainMethod(arguments) {
System.out.println("Storing arguments");
ArgumentRegistry.ARGS = arguments;
}
}
試してみるため、ClassUsingArgumentRegistry も作成しました。
public class ClassUsingArgumentRegistry {
public ClassUsingArgumentRegistry() {
System.out.println("Arguments: " + java.util.Arrays.toString(ArgumentRegistry.ARGS));
}
}
それでおしまい。AspectJ のコンパイル時ウィービングを有効にし、「java UnmodifyableClassWithMain Foo Bar Baz」を使用して結果を実行すると、次の出力が得られます。
Storing arguments
In main
Arguments: [foo, bar, baz]
Linuxは、それが保存し、コマンドラインを切り捨て、このソリューションは非常に限られていることに注意してください。 Javaコマンドラインは、多くの場合、非常に長いクラスパスを持っているように、これは非常に現実的な問題である。
ここでPablojimによって与えられた答えを実装するJavaコードがあります。
package test;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Test {
public static List<String> getLinuxCmdline(int maxBytesToRead) throws IOException {
List<String> result = new ArrayList<>();
String pid = new File("/proc/self").getCanonicalFile().getName();
File cmdlineFile = new File("/proc/" + pid + "/cmdline");
final int growBy = 1024;
try (FileInputStream is = new FileInputStream(cmdlineFile);) {
byte[] data = new byte[Math.min(growBy, maxBytesToRead)];
int totalRead = 0;
while (totalRead < maxBytesToRead) {
int read = is.read(data, totalRead, data.length - totalRead);
if (read > 0) {
totalRead += read;
if (data.length == totalRead) {
data = Arrays.copyOf(data, Math.min(data.length + growBy, maxBytesToRead));
}
} else {
break;
}
}
int start = 0;
int scan = 0;
while (scan < totalRead) {
if (data[scan] == 0) {
result.add(new String(Arrays.copyOfRange(data, start, scan)));
start = scan + 1;
}
scan++;
}
if (scan - start > 0) result.add(new String(Arrays.copyOfRange(data, start, scan))); }
return result;
}
public static void main(String[] args) throws IOException {
System.out.println(getLinuxCmdline(Integer.MAX_VALUE));
}
}
Eclipseの引数「fooのバー」でこれを実行すると、私のためにこれを提供します:
[/usr/lib/jvm/java-8-oracle/bin/java, -Dfile.encoding=UTF-8, -classpath, /home/mab/workspace/test/bin, test.Test, foo, bar]