In Java ist es eine Möglichkeit, die Befehlszeilenparameter auch wenn main () zu erhalten, hat sie nicht retten?

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

  •  21-08-2019
  •  | 
  •  

Frage

Wir haben ein Programm mit einer main (), der bestimmten CLPs parst aber sie nicht überall speichern. Ich habe dann meinen eigenen Plug-in-Code, der den Zugang zu dem ursprünglichen CLPs braucht es (so kann ich weitere Parameter übertragen). Allerdings kann ich nicht ändern main ()

ich sah, dass es offenbar ein Weg, dies in C # zu tun, ich bin auf der Suche für eine entsprechende Java-Lösung auf Linux.

UPDATE: Natürlich, ich bin mir dessen bewusst, wie main () funktioniert. Leider kann ich ändern, um die bestehende Anwendung oder die Art und Weise nicht aufgerufen wird (mit Ausnahme CLPs). Ich kann nur den Zugriff über einen Sandbox-Plugin-Code. Meine Frage ist, ob es einen Weg gibt, über die Befehlszeile (eher dann die Umgebungsvariablen mit -D), dass die JVM mit aufgerufen wurde zu erhalten.

War es hilfreich?

Lösung

Neben es in Haupt in irgendeiner Art und Weise zu tun Ich denke, die einzige andere Option, die Sie wären müssen Betriebssystemebene fallen zu lassen und einige Befehle ausführen, um die Argumente zu bekommen.

die cmd Zeilenargumente für einen laufenden Prozess unter Linux gespeichert unter / proc / pid / cmdline

sie So erhalten Sie die Prozess-ID finden müßten. Siehe hier:

Wie kann ein Java-Programm seine eigenen Prozess-ID bekommen?

Dann mit diesem offenen / proc / pid / cmdline und analysiert es. Das Format dieser Datei und ein Beispiel in c ist hier:

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

Es wäre am besten, diese beiden Anrufe in ein Shell-Skript zu wickeln, die Sie von Java aufrufen.

Bitte beachten Sie, dass diese extrem nicht tragbar sein wird und ist ein bisschen hacky. Aber wenn es sein muss ...

Andere Tipps

Die Lösung ist einfach, wenn man bedenkt, dass Java Hauptmethode ist nur eine andere statische Methode, die einen String-Array als Argument verwendet.

Erstellen Sie eine neue Klasse, die die CLPs speichert, ruft dann die alte Klasse. Später können Sie Ihre CLPs mit der neuen Klasse zugreifen:

import NotToBeChangedMainClass;

public MyMainClass {
  public static final String[] ARGUMENTS;
  public static void main(String ... args) {
    ARGUMENTS = args;
    NotToBeChangedMainClass.main(args);
  }

}

Schließlich Änderung unabhängig von externen Anrufern (z alle Batch-Dateien) MyMainClass statt NotToBeChangedMainClass zu verwenden. Wenn Sie fahrbare Gläser oder ähnliches verwenden, erfordert dies die entsprechende Konfigurationsdatei zu ändern.

Erstellen Sie Ihre eigene Hauptklasse. Speichern Sie die Argumente. Rufen Sie den alten main.

Es könnte einfacher sein, System.getProperty und -Dkey=value auf der Kommandozeile zu verwenden (vor Hauptklassennamen oder -jar).

Falls Sie haben keine Wahl jede Sie unbedingt haben alle vorhandenen Klassennamen behalten mit ihren genauen Namen ( wie in Ihrem Kommentar zu meiner vorherigen Antwort erwähnt), dann haben Sie gehen mit AspectJ.

Wir betrachten wir haben diese Klasse:

public class UnmodifyableClassWithMain {
  public static void main(String[] args) {
    System.out.println("In main");
    new ClassUsingArgumentRegistry();
  }
}

Als erstes müssen Sie etwas, das die Befehlszeilenargumente enthält. Ich werde eine einfache Klasse mit einem statischen Feld der Einfachheit halber verwendet werden:

public class ArgumentRegistry {
  public static String[] ARGS;
}

Dann müssen Sie Sie einen Aspect definieren, die Anrufe zu Haupt- und speichert die Argumente ab.

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;
  }

}

es auszuprobieren, habe ich auch eine ClassUsingArgumentRegistry:

public class ClassUsingArgumentRegistry {

  public ClassUsingArgumentRegistry() {
    System.out.println("Arguments: " + java.util.Arrays.toString(ArgumentRegistry.ARGS));
  }

}

Das ist es. Wenn ich AspectJ die Kompilierung Weben ermöglichen und das Ergebnis mit „java UnmodifyableClassWithMain Foo Bar Baz“ laufen lasse, erhalte ich die follwing Ausgabe:

Storing arguments
In main
Arguments: [foo, bar, baz]

Beachten Sie, dass diese Lösung sehr begrenzt ist, wie Linux über die Befehlszeile kürzt, die es speichert. Als Java-Befehlszeilen haben oft sehr lange CLASSPATHs, ist dies ein sehr reales Problem.

Dies ist Java-Code die Antwort von Pablojim Umsetzung.

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));
  }
}

Ausführen dieses mit Argumenten "foo bar" in Eclipse gibt es für mich:

[/usr/lib/jvm/java-8-oracle/bin/java, -Dfile.encoding=UTF-8, -classpath, /home/mab/workspace/test/bin, test.Test, foo, bar]
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top