Java에서는 main ()가 저장하지 않더라도 명령 줄 매개 변수를 얻는 방법이 있습니까?

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

  •  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의 예는 다음과 같습니다.

http://www.unix.com/unix-advanced-expert-users/86740-retrieving-command-line-arguments-particular-fid.html

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]
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top