2013-06-07 10 views
8

Contesto: eseguo alcuni test delle prestazioni su un'applicazione Java che viene avviata attraverso diversi livelli di riferimento indiretto, così che non sono del tutto sicuro che l'applicazione venga lanciata con le bandiere che penso sia. Vorrei che il mio applicazione per includere un controllo di integrità (prima che inizia la sua performance test) e includere nei risultati (dopo il test) informazioni su come la JVM è stato messo a punto, come ad esempio:All'interno di una JVM in esecuzione, come determinare a livello di codice le opzioni jvm utilizzate all'avvio?

  • Quali garbage collector era Usato?
  • Era/sta facendo attivamente cpu profiling?
  • Era/sta registrando attività gc?
  • Era/è in modalità -Xint o -Xmixed?
  • Era/è -XX:ParallelGCThreads set - se sì, a cosa, e in caso contrario, quale è l'impostazione predefinita per questa build?
  • Era/è -XX:UseCompressedOops acceso o spento?
  • ecc

C'è un modo per il codice Java per (all'interno di una JVM in esecuzione) interrogare le opzioni reali utilizzati per la sua JVM contenente? (Supponiamo che non riesca a vedere la riga di comando che mi ha lanciato, quindi non riesco a ri-analizzare quelle bandiere.)

Se non esiste un modo generale per determinarlo, le risposte specifiche per una particolare implementazione di JVM è anche benvenuta.

UPDATE:

E 'importante per la soluzione per essere in grado di sapere quali sono i valori di default sono per qualsiasi valore che non sia esplicitamente fornito sulla riga di comando. Altrimenti, coinvolgerà un sacco di legwork (a rischio di errore) per cercare quale sia il valore predefinito per una determinata combinazione JVM/piattaforma/versione/architettura. Sto testando una vasta gamma di JVM, quindi non voglio dover determinare manualmente quale sia l'impostazione predefinita per ogni parametro in ogni versione di jvm.

+0

È possibile elencare il processo JVM avviato da PID con 'ps -ef' e qui è possibile vedere tutti gli argomenti di input di quel processo. Questo dovrebbe funzionare per qualsiasi tipo di JVM. –

+0

@AlesJ. OP ha dichiarato che l'approccio a linea di comando non è un'opzione –

+0

@AlesJ. - Mi darebbe solo valori impostati in modo esplicito, quindi non otterrei alcuna informazione sui valori impliciti della JVM (vedi modifica aggiornamento alla domanda). :-( – Mickalot

risposta

2

Si potrebbe utilizzare un client JMX (come VisualVM) e quindi chiamare getVMOption(String name), vedere HotSpotDiagnosticMXBean.

Oppure, se è possibile passare almeno un set di flag per abilitare la registrazione JVM, deve essere --XX:+LogVMOutput -XX:LogFile=jvm.log e quindi analizzare l'output del log dall'app. Il registro contiene tutti i flag/parametri utilizzati per avviare la JVM.

Un'altra opzione è per elencare il processo JVM avviato da PID con ps -ef e lì è possibile visualizzare tutti gli argomenti di input di tale processo. Questo dovrebbe funzionare per qualsiasi tipo di JVM.

+0

non è HotSpotDiagnosticMXBean Oracle JVM specifico? –

+0

@OlegMikheev - Anche se non è l'ideale, mi accontenterò di qualsiasi soluzione specifica JVM (la maggior parte degli utenti sarà probabilmente su JVM Hotspot). Ma HotSpotDiagnosticMXBean sembra comunque il bean sbagliato ... mi dice cosa sono in atto i sistemi diagnostici (come quello che dovrebbe registrare quando si esegue un GC) piuttosto che il modo in cui la VM è sintonizzata. – Mickalot

+0

@AlesJ. - Ho provato alcuni jD Sun/Oracle J2SE (principalmente 1.6/1.7 32/64-bit su Linux), e nessuno sembra riconoscere -XX: + LogVMOutput. Anche io non lo vedo qui: http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html. Quale JVM stai usando che lo accetta? – Mickalot

5

È possibile ottenere gli argomenti della riga di comando da

ManagementFactory.getRuntimeMXBean().getInputArguments(); 
+0

Questo è stato anche il mio primo pensiero, ma può essere usato per determinare specifiche quali * quale garbage collector è stato usato *, * se è attivamente cpu profiling *, e così via? Credo che dovresti elaborare la tua risposta – Vulcan

+0

Lo apprezzo totalmente (e questa è stata la prima cosa che ho provato), ma il motivo per cui questo non è quello che sto cercando è perché se l'opzione JVM non è specificata, è impostata su qualunque sia l'impostazione predefinita della JVM, e non è 'presente in questa lista (che contiene solo argomenti esplicitamente specificati). Quindi non risponde alla domanda "Qual è l'impostazione predefinita per questa build?" Sto testando su molte macchine diverse, ognuna delle quali può avere un build leggermente diverso con lo slig valori predefiniti diversi. – Mickalot

2

Il seguente codice Java 7 elencherà tutte le opzioni JVM restituite da -XX:+PrintFlagsFinal. Tenta di utilizzare la reflection per accedere alla classe helper protetta da pacchetto Flag (disponibile da Java 6) e torna a HotSpotDiagnosticMXBean.getDiagnosticOptions() se non funziona.

// load the diagnostic bean first to avoid UnsatisfiedLinkError 
final HotSpotDiagnosticMXBean hsdiag = ManagementFactory 
     .getPlatformMXBean(HotSpotDiagnosticMXBean.class); 
List<VMOption> options; 
try { 
    final Class<?> flagClass = Class.forName("sun.management.Flag"); 
    final Method getAllFlagsMethod = flagClass.getDeclaredMethod("getAllFlags"); 
    final Method getVMOptionMethod = flagClass.getDeclaredMethod("getVMOption"); 
    getAllFlagsMethod.setAccessible(true); 
    getVMOptionMethod.setAccessible(true); 
    final Object result = getAllFlagsMethod.invoke(null); 
    final List<?> flags = (List<?>) result; 
    options = new ArrayList<VMOption>(flags.size()); 
    for (final Object flag : flags) { 
     options.add((VMOption) getVMOptionMethod.invoke(flag)); 
    } 
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException 
     | InvocationTargetException | ClassCastException e) { 
    if (hsdiag != null) { 
     // only includes writable external flags 
     options = hsdiag.getDiagnosticOptions(); 
    } else { 
     options = Collections.emptyList(); 
    } 
} 
final Map<String, VMOption> optionMap = new TreeMap<>(); 
for (final VMOption option : options) { 
    optionMap.put(option.getName(), option); 
} 
for (final VMOption option : optionMap.values()) { 
    System.out.println(option.getName() + " = " + option.getValue() + " (" + 
      option.getOrigin() + ", " + 
      (option.isWriteable() ? "read-write" : "read-only") + ")"); 
} 
System.out.println(options.size() + " options found"); 

Con 7u71, ottengo 663 opzioni, o con -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions, 779.