# Ermittlung und Auflistung interner Hotspot JVM Optionen der aktuellen JVM Instanz



## Thomas Darimont (19. Oktober 2011)

Hallo,

unter http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html 
findet man eine Aufstellung aller JVM Optionen die man bei Sun / Oracle basierten JVMs tunen kann.

Diese Liste ist aber leider nicht vollständig, denn es gibt noch viel mehr interne JVM Optionen die dort nicht genannt werden.

Hier mal an Beispiel wie man an eine umfangreichere Liste von JVM Optionen mit den Werten der aktuellen JVM Instanz inklusive defaults kommt:


```
package de.tutorials.training;

import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.net.URL;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.openmbean.CompositeData;

public class JvmOptionsAnalyzer {

  //private final String supportedOptionCategories = "diagnostic|develop|notproduct|product_pd|product";
  private final String supportedOptionCategories = "product";
  
  /*
   * Thank god for the invention of code conventions *g*
   */
  private final Pattern defaultOpenJdkJvmOptionExtractorPattern = Pattern.compile("\\s*(" + supportedOptionCategories + ")\\([\\w\\d]+,\\s*([\\w\\d]+)\\s*,\\s[\\w\\d]+.*\\\\");

  @SuppressWarnings("serial")
  private final Map<String, Pattern> jvmOptionSourceUrlsToOptionPatternMap = new LinkedHashMap<String, Pattern>() {
    {
      put(
        "http://hg.openjdk.java.net/jdk7/hotspot-gc/hotspot/raw-file/162b62460264/src/share/vm/runtime/globals.hpp",
        defaultOpenJdkJvmOptionExtractorPattern);
      put(
        "http://hg.openjdk.java.net/jdk7/build/hotspot/raw-file/cd8e33b2a8ad/src/share/vm/gc_implementation/g1/g1_globals.hpp",
        defaultOpenJdkJvmOptionExtractorPattern);
    }
  };

  private final Map<String, Set<String>> alreadyFoundJvmOptions = new TreeMap<String, Set<String>>();
  
  public static void main(String[] args) throws Exception {
    new JvmOptionsAnalyzer().listCurrentJVMOptions();
  }


  private void listCurrentJVMOptions() {
    printCurrentJVMVersion();
    downloadOpenJdkVMOptionList();
    printJvmOptionSummary();
    printCurrentJVMOptions();
  }


  private void printCurrentJVMVersion() {
    RuntimeMXBean rmxb = ManagementFactory.getRuntimeMXBean();
    System.out.printf("%s %s %s %s", System.getProperty("java.version"), rmxb.getVmVersion(), rmxb.getVmName(),rmxb.getVmVendor()).println();
  }


  private void printCurrentJVMOptions() {
    JvmOptionAccessor joa = new JvmOptionAccessor();
    for (Map.Entry<String, Set<String>> options : alreadyFoundJvmOptions.entrySet()) {
      String categoryName = options.getKey();
      System.out.println("#### Options in Category: " + categoryName + " " + options.getValue().size());

      for (String optionName : options.getValue()) {
        Object vmOption = joa.getVMOption(optionName);
        if (vmOption == null) {
          System.out.println(optionName + " is not supported by this JVM");
        } else {
          // Name, Origin, Value, Writeable
          System.out.println(vmOption);
        }
      }
    }
  }


  private void downloadOpenJdkVMOptionList() {
    for (Map.Entry<String, Pattern> sourceUrlToOptionPatternMap : jvmOptionSourceUrlsToOptionPatternMap.entrySet()) {
      String jvmOptionSourceUrl = sourceUrlToOptionPatternMap.getKey();
      Pattern optionExtractorPattern = sourceUrlToOptionPatternMap.getValue();
      loadJvmOptionsFromSourceUrl(jvmOptionSourceUrl, alreadyFoundJvmOptions, optionExtractorPattern);
    }
  }


  private void printJvmOptionSummary() {
    System.out.println("##### JvmOptionSummary:");
    for (String optionCategory : alreadyFoundJvmOptions.keySet()) {
      System.out.println("Options in Category: " + optionCategory + ": "
        + alreadyFoundJvmOptions.get(optionCategory).size());
    }
    System.out.println("#####");
  }


  private void loadJvmOptionsFromSourceUrl(String jvmOptionSourceUrl, Map<String, Set<String>> alreadyFoundJvmOptions, Pattern optionExtractorPattern) {
    System.out.println("loading options from: " + jvmOptionSourceUrl);
    Scanner scanner = null;
    try {
      scanner = new Scanner(new URL(jvmOptionSourceUrl).openStream());
      while (scanner.hasNextLine()) {
        String line = scanner.nextLine();
        Matcher matcher = optionExtractorPattern.matcher(line);
        if (matcher.matches()) {
          String optionCategory = matcher.group(1);
          String optionName = matcher.group(2);

          registerJvmOption(alreadyFoundJvmOptions, optionCategory, optionName);
        }
      }
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      scanner.close();
    }
    System.out.println("done.");
  }


  protected void registerJvmOption(Map<String, Set<String>> alreadyFoundJvmOptions, String optionCategory, String optionName) {
    Set<String> optionNames = alreadyFoundJvmOptions.get(optionCategory);
    if (optionNames == null) {
      optionNames = new TreeSet<String>();
      alreadyFoundJvmOptions.put(optionCategory, optionNames);
    }
    optionNames.add(optionName);
  }

  static class JvmOptionAccessor {

    private final static String GET_VM_OPTION_METHOD_NAME = "getVMOption";
    private final static String HOTSPOT_DIAGNOSTICS_OBJECT_NAME = "com.sun.management:type=HotSpotDiagnostic";
    private MBeanServer platformMBeanServer;
    private ObjectName hotSpotDiagnosticName;


    public JvmOptionAccessor() {
      try {
        platformMBeanServer = ManagementFactory.getPlatformMBeanServer();
        hotSpotDiagnosticName = new ObjectName(HOTSPOT_DIAGNOSTICS_OBJECT_NAME);
      } catch (MalformedObjectNameException e) {
        throw new RuntimeException(e);
      } catch (NullPointerException e) {
        throw new RuntimeException(e);
      }
    }


    public Object getVMOption(String optionName) {
      Object result = null;
      try {
        Object[] paramValues = new Object[] { optionName };
        String[] paramTypes = new String[] { String.class.getName() };
        CompositeData cd = (CompositeData) platformMBeanServer.invoke(hotSpotDiagnosticName,GET_VM_OPTION_METHOD_NAME, paramValues, paramTypes);
        result = cd != null ? cd.values() : null;
      } catch (Exception e) {
        // ignore
      }
      return result;
    }
  }
}
```

Anbei zwei Beispielausgaben für eine Oracle JVM 1.6.x und 1.7.x unter 64-Bit Windows


Gruß Tom


----------



## SE (19. Oktober 2011)

Da hab ich aber n Veto einzulegen !
Anhand der verwendeten Links welche schon OpenJDK im namen stehen haben gehe ich davon aus das man damit sicher nicht an die Flags einer Sun/Oracle VM herankommt da die Informaitonen auch nur von einem SpreadSheet aus dem Netz geladen werden.


----------



## Thomas Darimont (19. Oktober 2011)

Hallo,

na ja, OpenJdk basiert ja (zumindest Teilweise) auf dem Code der Sun JVM. Deshalb gibt es da eine gewisse abwärts) Kompatibilität was die internen switches angeht... von daher würde ich schon sagen, dass man das durchaus verwenden kann um eine umfangreichere Übersicht zu bekommen. Wie du den Beispielen für (1.6 und 1.7er JVMs 1.5 hab ich leider nicht mehr Installiert) entnehmen kannst kommt auch (bis auf wenige Ausnahmen) tatsächlich ein entsprechende VMOptions Informationen zurück.
Deshalb würde ich mal behaupten, dass beim obigen Ansatz doch etwas mehr Information entsteht als die "offiziell" verfügbaren Tabellen mit JVM Switches bieten können.

Diese JVM Switches gelten, wie im Beitrag schon genannt nur für OpenJDK, Sun / Oracle JVMs (natürlich nicht JRockit). Andere JVMs, beispielsweise von IBM  oder HP haben natürlich andere JVM Switches.


Gruß Tom


----------



## SE (19. Oktober 2011)

Ja ... versteh ich doch ... ich wollte lediglich mit zum ausdruck bringen das man nicht an ALLE Switches der Oracle VM kommt ... und es sicherlich auch passieren kann das man in dieser Liste *welche ja nun mal fürs OpenJDK ist* switches hat welche es in der Oracle VM überhaupt nicht gibt. Das ein großteil kompatibel ist ist klar da ja zumindest seit v7 das OpenJDK die offizielle Referenzimplementierung darstellt ... aber 100% passen wird es nicht.


----------



## Thomas Darimont (19. Oktober 2011)

Hallo,

Code ist jetzt auf github:
https://github.com/thomasdarimont/jvmoa

Gruß Tom


----------



## Thomas Darimont (7. November 2011)

Hallo,

es gibt auch noch eine andere Möglichkeit alle JVM Einstellungen einer "lokalen" JVM auszugeben:

```
java -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal -version
```

Mit:  -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal wird eine Liste der JVM Optionen ausgegeben.
Dieses Flag stand auch in den beiden oben angehängten TXT Dateien drinnen: PrintFlagsFinal
Quelle: http://www.jroller.com/ethdsy/entry/print_all_jvm_flags 
Danke an Heinz Kabutz für den Tipp ;-)

-version ist notwendig, damit die JVM gestartet wird... 

Gruß Tom


----------



## Thomas Darimont (23. Mai 2013)

Hallo,

hier findet man noch eine umfangreiche Liste mit JVM Optionen mit Erklärung:
http://stas-blogspot.blogspot.de/2011/07/most-complete-list-of-xx-options-for.html

Gruß Tom


----------

