Java에서는 main ()가 저장하지 않더라도 명령 줄 매개 변수를 얻는 방법이 있습니까?
-
21-08-2019 - |
문제
우리는 특정 CLP를 구문 분석하지만 어디서나 저장하지 않는 Main ()이있는 프로그램이 있습니다. 그런 다음 원래 CLP에 액세스 해야하는 내 자신의 플러그인 코드가있어서 더 많은 매개 변수를 전송할 수 있습니다. 그러나 나는 main ()을 변경할 수 없다
나는 c#에 이것을하는 방법이 분명히 있다는 것을 알았다., Linux에서 동등한 Java 솔루션을 찾고 있습니다.
업데이트 : 분명히 Main ()가 어떻게 작동하는지 알고 있습니다. 불행히도, 기존 응용 프로그램이나 호출 방식 (CLP 제외)을 변경할 수 없습니다. 샌드 박스 플러그인 코드를 통해서만 액세스 할 수 있습니다. 내 질문은 JVM이 호출 된 명령 줄 (-D가있는 환경 변수)을 얻는 방법이 있는지 여부입니다.
해결책
어떤 식 으로든 메인으로하는 것 외에도 운영 체제 수준으로 떨어지고 인수를 얻기 위해 일부 명령을 실행하는 것입니다.
Linux에서 실행중인 프로세스에 대한 CMD 라인 인수는 다음에 저장됩니다. /Proc/PID/cmdline
따라서 그들을 얻으려면 프로세스 ID를 찾아야합니다. 여기를 봐:
Java 프로그램은 어떻게 자체 프로세스 ID를 얻을 수 있습니까?
그런 다음이 열린 사용 /Proc/PID/cmdline 그리고 그것을 구문 분석합니다. 이 파일의 형식과 C의 예는 다음과 같습니다.
Java에서 호출하는 하나의 쉘 스크립트 로이 두 통화를 랩핑하는 것이 가장 좋습니다.
이것은 매우 휴대가 가능하지 않으며 약간 해킹됩니다. 그러나 필요가 필요하다면 ...
다른 팁
Java의 주요 방법이 문자열 배열을 인수로 취하는 또 다른 정적 메소드라는 것을 알면 솔루션은 쉽습니다.
CLP를 저장하는 새로운 클래스를 만들고 구형 클래스를 호출하십시오. 나중에 새 클래스를 사용하여 CLP에 액세스 할 수 있습니다.
import NotToBeChangedMainClass;
public MyMainClass {
public static final String[] ARGUMENTS;
public static void main(String ... args) {
ARGUMENTS = args;
NotToBeChangedMainClass.main(args);
}
}
마지막으로, 외부 발신자 (예 : 배치 파일)를 변경하여 NotTobeChangedMainClass 대신 MyMainClass를 사용하십시오. Runable Jars 또는 이와 유사한 것을 사용하는 경우 적절한 구성 파일을 변경해야합니다.
나만의 메인 클래스를 만듭니다. 인수를 저장하십시오. 노인을 부르십시오 main
.
사용하기가 더 쉬울 수 있습니다 System.getProperty
그리고 -Dkey=value
명령 줄에서 (메인 클래스 이름 또는 -jar
).
선택의 여지가없는 경우, 정확한 이름으로 기존 클래스 이름을 모두 보유 해야하는 경우 (귀하의 의견에 명시된 바와 같이 내 이전 답변에), 당신은 SAGONT와 함께 가야합니다.
이 수업이 있다고 생각합시다.
public class UnmodifyableClassWithMain {
public static void main(String[] args) {
System.out.println("In main");
new ClassUsingArgumentRegistry();
}
}
먼저, 당신은 명령 줄 인수를 보유하는 무언가가 필요합니다. 단순성을 위해 정적 필드가있는 간단한 클래스를 사용하겠습니다.
public class ArgumentRegistry {
public static String[] ARGS;
}
그런 다음 메인으로 호출을 가로 채고 인수를 저장하는 측면을 정의해야합니다.
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"를 사용하여 결과를 실행하면 follwing 출력을 얻습니다.
Storing arguments
In main
Arguments: [foo, bar, baz]
이 솔루션은 Linux가 저장하는 명령 줄을 잘라서 매우 제한적입니다. Java Command Lines는 종종 Classpath가 매우 길기 때문에 이것은 매우 실제적인 문제입니다.
다음은 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 bar"인수와 함께 이것을 실행하면 다음과 같습니다.
[/usr/lib/jvm/java-8-oracle/bin/java, -Dfile.encoding=UTF-8, -classpath, /home/mab/workspace/test/bin, test.Test, foo, bar]