package org.xbib.elasticsearch.common.jvm; import org.elasticsearch.common.Strings; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.io.stream.Streamable; import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilderString; import java.io.IOException; import java.lang.management.BufferPoolMXBean; import java.lang.management.ClassLoadingMXBean; import java.lang.management.GarbageCollectorMXBean; import java.lang.management.ManagementFactory; import java.lang.management.MemoryMXBean; import java.lang.management.MemoryPoolMXBean; import java.lang.management.MemoryUsage; import java.lang.management.RuntimeMXBean; import java.lang.management.ThreadMXBean; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class JvmInfo implements Streamable, ToXContent { public static final String YOUNG = "young"; public static final String OLD = "old"; public static final String SURVIVOR = "survivor"; private final static RuntimeMXBean runtimeMXBean; private final static MemoryMXBean memoryMXBean; private final static ThreadMXBean threadMXBean; private final static ClassLoadingMXBean classLoadingMXBean; private static JvmInfo INSTANCE; static { runtimeMXBean = ManagementFactory.getRuntimeMXBean(); memoryMXBean = ManagementFactory.getMemoryMXBean(); threadMXBean = ManagementFactory.getThreadMXBean(); classLoadingMXBean = ManagementFactory.getClassLoadingMXBean(); long pid; String xPid = runtimeMXBean.getName(); try { xPid = xPid.split("@")[0]; pid = Long.parseLong(xPid); } catch (Exception e) { pid = -1; } JvmInfo info = new JvmInfo(); info.pid = pid; info.startTime = runtimeMXBean.getStartTime(); info.version = runtimeMXBean.getSystemProperties().get("java.version"); info.vmName = runtimeMXBean.getVmName(); info.vmVendor = runtimeMXBean.getVmVendor(); info.vmVersion = runtimeMXBean.getVmVersion(); /* TODO without sun.misc.VM, read from argument line somehow? try { Class<?> vmClass = Class.forName("sun.misc.VM"); info.mem.directMemoryMax = (Long) vmClass.getMethod("maxDirectMemory").invoke(null); } catch (Throwable t) { // ignore }*/ info.inputArguments = runtimeMXBean.getInputArguments().toArray(new String[runtimeMXBean.getInputArguments().size()]); info.bootClassPath = runtimeMXBean.getBootClassPath(); info.classPath = runtimeMXBean.getClassPath(); info.systemProperties = runtimeMXBean.getSystemProperties(); List<GarbageCollectorMXBean> gcMxBeans = ManagementFactory.getGarbageCollectorMXBeans(); info.gcCollectors = new String[gcMxBeans.size()]; for (int i = 0; i < gcMxBeans.size(); i++) { GarbageCollectorMXBean gcMxBean = gcMxBeans.get(i); info.gcCollectors[i] = gcMxBean.getName(); } List<MemoryPoolMXBean> memoryPoolMXBeans = ManagementFactory.getMemoryPoolMXBeans(); info.memoryPools = new String[memoryPoolMXBeans.size()]; for (int i = 0; i < memoryPoolMXBeans.size(); i++) { MemoryPoolMXBean memoryPoolMXBean = memoryPoolMXBeans.get(i); info.memoryPools[i] = memoryPoolMXBean.getName(); } info.stats = readStats(); INSTANCE = info; } public Stats stats; long pid = -1; String version = ""; String vmName = ""; String vmVersion = ""; String vmVendor = ""; long startTime = -1; String[] inputArguments; String bootClassPath; String classPath; Map<String, String> systemProperties; String[] gcCollectors = Strings.EMPTY_ARRAY; String[] memoryPools = Strings.EMPTY_ARRAY; private JvmInfo() { } public static JvmInfo getInstance() { return INSTANCE; } public static Stats readStats() { Stats stats = new Stats(); stats.timestamp = System.currentTimeMillis(); stats.uptime = runtimeMXBean.getUptime(); stats.mem = new Mem(); MemoryUsage memUsage = memoryMXBean.getHeapMemoryUsage(); stats.mem.heapInit = memUsage.getInit() < 0 ? 0 : memUsage.getInit(); stats.mem.heapUsed = memUsage.getUsed() < 0 ? 0 : memUsage.getUsed(); stats.mem.heapCommitted = memUsage.getCommitted() < 0 ? 0 : memUsage.getCommitted(); stats.mem.heapMax = memUsage.getMax() < 0 ? 0 : memUsage.getMax(); memUsage = memoryMXBean.getNonHeapMemoryUsage(); stats.mem.nonHeapInit = memUsage.getInit() < 0 ? 0 : memUsage.getInit(); stats.mem.nonHeapUsed = memUsage.getUsed() < 0 ? 0 : memUsage.getUsed(); stats.mem.nonHeapCommitted = memUsage.getCommitted() < 0 ? 0 : memUsage.getCommitted(); stats.mem.nonHeapMax = memUsage.getMax() < 0 ? 0 : memUsage.getMax(); List<MemoryPoolMXBean> memoryPoolMXBeans = ManagementFactory.getMemoryPoolMXBeans(); List<MemoryPool> pools = new ArrayList<>(); for (int i = 0; i < memoryPoolMXBeans.size(); i++) { try { MemoryPoolMXBean memoryPoolMXBean = memoryPoolMXBeans.get(i); MemoryUsage usage = memoryPoolMXBean.getUsage(); MemoryUsage peakUsage = memoryPoolMXBean.getPeakUsage(); String name = getByMemoryPoolName(memoryPoolMXBean.getName(), null); if (name == null) { // if we can't resolve it, its not interesting.... (Per Gen, Code Cache) continue; } pools.add(new MemoryPool(name, usage.getUsed() < 0 ? 0 : usage.getUsed(), usage.getMax() < 0 ? 0 : usage.getMax(), peakUsage.getUsed() < 0 ? 0 : peakUsage.getUsed(), peakUsage.getMax() < 0 ? 0 : peakUsage.getMax() )); } catch (OutOfMemoryError err) { throw err; // rethrow } catch (Throwable ex) { /* ignore some JVMs might barf here with: * java.lang.InternalError: Memory Pool not found * we just omit the pool in that case!*/ } } stats.mem.pools = pools.toArray(new MemoryPool[pools.size()]); stats.threads = new Threads(); stats.threads.count = threadMXBean.getThreadCount(); stats.threads.peakCount = threadMXBean.getPeakThreadCount(); List<GarbageCollectorMXBean> gcMxBeans = ManagementFactory.getGarbageCollectorMXBeans(); stats.gc = new GarbageCollectors(); stats.gc.collectors = new GarbageCollector[gcMxBeans.size()]; for (int i = 0; i < stats.gc.collectors.length; i++) { GarbageCollectorMXBean gcMxBean = gcMxBeans.get(i); stats.gc.collectors[i] = new GarbageCollector(); stats.gc.collectors[i].name = getByGcName(gcMxBean.getName(), gcMxBean.getName()); stats.gc.collectors[i].collectionCount = gcMxBean.getCollectionCount(); stats.gc.collectors[i].collectionTime = gcMxBean.getCollectionTime(); } try { List<BufferPoolMXBean> bufferPools = ManagementFactory.getPlatformMXBeans(BufferPoolMXBean.class); stats.bufferPools = new ArrayList<>(bufferPools.size()); for (BufferPoolMXBean bufferPool : bufferPools) { stats.bufferPools.add(new BufferPool(bufferPool.getName(), bufferPool.getCount(), bufferPool.getTotalCapacity(), bufferPool.getMemoryUsed())); } } catch (Throwable t) { // buffer pools are not available } stats.classes = new Classes(); stats.classes.loadedClassCount = classLoadingMXBean.getLoadedClassCount(); stats.classes.totalLoadedClassCount = classLoadingMXBean.getTotalLoadedClassCount(); stats.classes.unloadedClassCount = classLoadingMXBean.getUnloadedClassCount(); return stats; } public static String getByMemoryPoolName(String poolName, String defaultName) { if ("Eden Space".equals(poolName) || "PS Eden Space".equals(poolName) || "Par Eden Space".equals(poolName) || "G1 Eden Space".equals(poolName)) { return YOUNG; } if ("Survivor Space".equals(poolName) || "PS Survivor Space".equals(poolName) || "Par Survivor Space".equals(poolName) || "G1 Survivor Space".equals(poolName)) { return SURVIVOR; } if ("Tenured Gen".equals(poolName) || "PS Old Gen".equals(poolName) || "CMS Old Gen".equals(poolName) || "G1 Old Gen".equals(poolName)) { return OLD; } return defaultName; } public static String getByGcName(String gcName, String defaultName) { if ("Copy".equals(gcName) || "PS Scavenge".equals(gcName) || "ParNew".equals(gcName) || "G1 Young Generation".equals(gcName)) { return YOUNG; } if ("MarkSweepCompact".equals(gcName) || "PS MarkSweep".equals(gcName) || "ConcurrentMarkSweep".equals(gcName) || "G1 Old Generation".equals(gcName)) { return OLD; } return defaultName; } public static JvmInfo readJvmInfo(StreamInput in) throws IOException { JvmInfo jvmInfo = new JvmInfo(); jvmInfo.readFrom(in); return jvmInfo; } public long pid() { return this.pid; } public long getPid() { return pid; } public String version() { return this.version; } public String getVersion() { return this.version; } public int versionAsInteger() { try { int i = 0; String sVersion = ""; for (; i < version.length(); i++) { if (!Character.isDigit(version.charAt(i)) && version.charAt(i) != '.') { break; } if (version.charAt(i) != '.') { sVersion += version.charAt(i); } } if (i == 0) { return -1; } return Integer.parseInt(sVersion); } catch (Exception e) { return -1; } } public int versionUpdatePack() { try { int i = 0; String sVersion = ""; for (; i < version.length(); i++) { if (!Character.isDigit(version.charAt(i)) && version.charAt(i) != '.') { break; } if (version.charAt(i) != '.') { sVersion += version.charAt(i); } } if (i == 0) { return -1; } Integer.parseInt(sVersion); int from; if (version.charAt(i) == '_') { // 1.7.0_4 from = ++i; } else if (version.charAt(i) == '-' && version.charAt(i + 1) == 'u') { // 1.7.0-u2-b21 i = i + 2; from = i; } else { return -1; } for (; i < version.length(); i++) { if (!Character.isDigit(version.charAt(i)) && version.charAt(i) != '.') { break; } } if (from == i) { return -1; } return Integer.parseInt(version.substring(from, i)); } catch (Exception e) { return -1; } } public String getVmName() { return this.vmName; } public String getVmVersion() { return this.vmVersion; } public String getVmVendor() { return this.vmVendor; } public long getStartTime() { return this.startTime; } public String[] getInputArguments() { return this.inputArguments; } public String getBootClassPath() { return this.bootClassPath; } public String getClassPath() { return this.classPath; } public Map<String, String> getSystemProperties() { return this.systemProperties; } @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { builder.startObject(Fields.JVM); builder.field(Fields.TIMESTAMP, stats.timestamp); builder.dateValueField(Fields.START_TIME_IN_MILLIS, Fields.START_TIME, startTime); builder.timeValueField(Fields.UPTIME_IN_MILLIS, Fields.UPTIME, stats.uptime); builder.field(Fields.PID, pid); builder.field(Fields.VERSION, version); builder.field(Fields.VM_NAME, vmName); builder.field(Fields.VM_VERSION, vmVersion); builder.field(Fields.VM_VENDOR, vmVendor); if (stats.threads != null) { builder.startObject(Fields.THREADS); builder.field(Fields.COUNT, stats.threads.getCount()); builder.field(Fields.PEAK_COUNT, stats.threads.getPeakCount()); builder.endObject(); } builder.field(Fields.MEMORY_POOLS, memoryPools); if (stats.mem != null) { builder.startObject(Fields.MEM); builder.startObject(Fields.POOLS); for (MemoryPool pool : stats.mem) { builder.startObject(pool.getName(), XContentBuilder.FieldCaseConversion.NONE); builder.byteSizeField(Fields.USED_IN_BYTES, Fields.USED, pool.used); builder.byteSizeField(Fields.MAX_IN_BYTES, Fields.MAX, pool.max); builder.byteSizeField(Fields.PEAK_USED_IN_BYTES, Fields.PEAK_USED, pool.peakUsed); builder.byteSizeField(Fields.PEAK_MAX_IN_BYTES, Fields.PEAK_MAX, pool.peakMax); builder.endObject(); } builder.endObject(); if (stats.mem.getHeapUsedPercent() >= 0) { builder.field(Fields.HEAP_USED_PERCENT, stats.mem.getHeapUsedPercent()); } builder.byteSizeField(Fields.HEAP_INIT_IN_BYTES, Fields.HEAP_INIT, stats.mem.heapInit); builder.byteSizeField(Fields.HEAP_USED_IN_BYTES, Fields.HEAP_USED, stats.mem.heapUsed); builder.byteSizeField(Fields.HEAP_COMMITTED_IN_BYTES, Fields.HEAP_COMMITTED, stats.mem.heapCommitted); builder.byteSizeField(Fields.HEAP_MAX_IN_BYTES, Fields.HEAP_MAX, stats.mem.heapMax); builder.byteSizeField(Fields.NON_HEAP_INIT_IN_BYTES, Fields.NON_HEAP_INIT, stats.mem.nonHeapInit); builder.byteSizeField(Fields.NON_HEAP_USED_IN_BYTES, Fields.NON_HEAP_USED, stats.mem.nonHeapUsed); builder.byteSizeField(Fields.NON_HEAP_COMMITTED_IN_BYTES, Fields.NON_HEAP_COMMITTED, stats.mem.nonHeapCommitted); builder.byteSizeField(Fields.NON_HEAP_MAX_IN_BYTES, Fields.NON_HEAP_MAX, stats.mem.nonHeapMax); builder.byteSizeField(Fields.DIRECT_MAX_IN_BYTES, Fields.DIRECT_MAX, stats.mem.directMemoryMax); builder.endObject(); } builder.field(Fields.GC_COLLECTORS, gcCollectors); if (stats.gc != null) { builder.startObject(Fields.GC); builder.startObject(Fields.COLLECTORS); for (GarbageCollector collector : stats.gc) { builder.startObject(collector.getName(), XContentBuilder.FieldCaseConversion.NONE); builder.field(Fields.COLLECTION_COUNT, collector.getCollectionCount()); builder.timeValueField(Fields.COLLECTION_TIME_IN_MILLIS, Fields.COLLECTION_TIME, collector.collectionTime); builder.endObject(); } builder.endObject(); builder.endObject(); } if (stats.bufferPools != null) { builder.startObject(Fields.BUFFER_POOLS); for (BufferPool bufferPool : stats.bufferPools) { builder.startObject(bufferPool.getName(), XContentBuilder.FieldCaseConversion.NONE); builder.field(Fields.COUNT, bufferPool.getCount()); builder.byteSizeField(Fields.USED_IN_BYTES, Fields.USED, bufferPool.used); builder.byteSizeField(Fields.TOTAL_CAPACITY_IN_BYTES, Fields.TOTAL_CAPACITY, bufferPool.totalCapacity); builder.endObject(); } builder.endObject(); } if (stats.classes != null) { builder.startObject(Fields.CLASSES); builder.field(Fields.CURRENT_LOADED_COUNT, stats.classes.getLoadedClassCount()); builder.field(Fields.TOTAL_LOADED_COUNT, stats.classes.getTotalLoadedClassCount()); builder.field(Fields.TOTAL_UNLOADED_COUNT, stats.classes.getUnloadedClassCount()); builder.endObject(); } builder.endObject(); return builder; } @Override public void readFrom(StreamInput in) throws IOException { pid = in.readLong(); version = in.readString(); vmName = in.readString(); vmVersion = in.readString(); vmVendor = in.readString(); startTime = in.readLong(); inputArguments = new String[in.readInt()]; for (int i = 0; i < inputArguments.length; i++) { inputArguments[i] = in.readString(); } bootClassPath = in.readString(); classPath = in.readString(); systemProperties = new HashMap<>(); int size = in.readInt(); for (int i = 0; i < size; i++) { systemProperties.put(in.readString(), in.readString()); } stats.timestamp = in.readVLong(); stats.uptime = in.readVLong(); stats.threads = Threads.readThreads(in); memoryPools = in.readStringArray(); stats.mem = Mem.readMem(in); gcCollectors = in.readStringArray(); stats.gc = GarbageCollectors.readGarbageCollectors(in); if (in.readBoolean()) { size = in.readVInt(); stats.bufferPools = new ArrayList<>(size); for (int i = 0; i < size; i++) { BufferPool bufferPool = new BufferPool(); bufferPool.readFrom(in); stats.bufferPools.add(bufferPool); } } } @Override public void writeTo(StreamOutput out) throws IOException { out.writeLong(pid); out.writeString(version); out.writeString(vmName); out.writeString(vmVersion); out.writeString(vmVendor); out.writeLong(startTime); out.writeInt(inputArguments.length); for (String inputArgument : inputArguments) { out.writeString(inputArgument); } out.writeString(bootClassPath); out.writeString(classPath); out.writeInt(systemProperties.size()); for (Map.Entry<String, String> entry : systemProperties.entrySet()) { out.writeString(entry.getKey()); out.writeString(entry.getValue()); } out.writeVLong(stats.timestamp); out.writeVLong(stats.uptime); stats.threads.writeTo(out); out.writeStringArray(memoryPools); stats.mem.writeTo(out); out.writeStringArray(gcCollectors); stats.gc.writeTo(out); if (stats.bufferPools == null) { out.writeBoolean(false); } else { out.writeBoolean(true); out.writeVInt(stats.bufferPools.size()); for (BufferPool bufferPool : stats.bufferPools) { bufferPool.writeTo(out); } } } public static class Stats { long timestamp = -1; long uptime; Threads threads; Mem mem; GarbageCollectors gc; List<BufferPool> bufferPools; Classes classes; public long getTimestamp() { return timestamp; } public Mem getMem() { return mem; } public GarbageCollectors getGc() { return gc; } } static final class Fields { static final XContentBuilderString JVM = new XContentBuilderString("jvm"); static final XContentBuilderString PID = new XContentBuilderString("pid"); static final XContentBuilderString VERSION = new XContentBuilderString("version"); static final XContentBuilderString VM_NAME = new XContentBuilderString("vm_name"); static final XContentBuilderString VM_VERSION = new XContentBuilderString("vm_version"); static final XContentBuilderString VM_VENDOR = new XContentBuilderString("vm_vendor"); static final XContentBuilderString TIMESTAMP = new XContentBuilderString("timestamp"); static final XContentBuilderString START_TIME = new XContentBuilderString("start_time"); static final XContentBuilderString START_TIME_IN_MILLIS = new XContentBuilderString("start_time_in_millis"); static final XContentBuilderString UPTIME = new XContentBuilderString("uptime"); static final XContentBuilderString UPTIME_IN_MILLIS = new XContentBuilderString("uptime_in_millis"); static final XContentBuilderString THREADS = new XContentBuilderString("threads"); static final XContentBuilderString COUNT = new XContentBuilderString("count"); static final XContentBuilderString PEAK_COUNT = new XContentBuilderString("peak_count"); static final XContentBuilderString DIRECT_MAX = new XContentBuilderString("direct_max"); static final XContentBuilderString DIRECT_MAX_IN_BYTES = new XContentBuilderString("direct_max_in_bytes"); static final XContentBuilderString MEMORY_POOLS = new XContentBuilderString("memory_pools"); static final XContentBuilderString MEM = new XContentBuilderString("mem"); static final XContentBuilderString HEAP_INIT = new XContentBuilderString("heap_init"); static final XContentBuilderString HEAP_INIT_IN_BYTES = new XContentBuilderString("heap_init_in_bytes"); static final XContentBuilderString HEAP_USED = new XContentBuilderString("heap_used"); static final XContentBuilderString HEAP_USED_IN_BYTES = new XContentBuilderString("heap_used_in_bytes"); static final XContentBuilderString HEAP_COMMITTED = new XContentBuilderString("heap_committed"); static final XContentBuilderString HEAP_COMMITTED_IN_BYTES = new XContentBuilderString("heap_committed_in_bytes"); static final XContentBuilderString HEAP_MAX = new XContentBuilderString("heap_max"); static final XContentBuilderString HEAP_MAX_IN_BYTES = new XContentBuilderString("heap_max_in_bytes"); static final XContentBuilderString HEAP_USED_PERCENT = new XContentBuilderString("heap_used_percent"); static final XContentBuilderString NON_HEAP_INIT = new XContentBuilderString("non_heap_init"); static final XContentBuilderString NON_HEAP_INIT_IN_BYTES = new XContentBuilderString("non_heap_init_in_bytes"); static final XContentBuilderString NON_HEAP_USED = new XContentBuilderString("non_heap_used"); static final XContentBuilderString NON_HEAP_USED_IN_BYTES = new XContentBuilderString("non_heap_used_in_bytes"); static final XContentBuilderString NON_HEAP_COMMITTED = new XContentBuilderString("non_heap_committed"); static final XContentBuilderString NON_HEAP_COMMITTED_IN_BYTES = new XContentBuilderString("non_heap_committed_in_bytes"); static final XContentBuilderString NON_HEAP_MAX = new XContentBuilderString("non_heap_max"); static final XContentBuilderString NON_HEAP_MAX_IN_BYTES = new XContentBuilderString("non_heap_max_in_bytes"); static final XContentBuilderString POOLS = new XContentBuilderString("pools"); static final XContentBuilderString USED = new XContentBuilderString("used"); static final XContentBuilderString USED_IN_BYTES = new XContentBuilderString("used_in_bytes"); static final XContentBuilderString MAX = new XContentBuilderString("max"); static final XContentBuilderString MAX_IN_BYTES = new XContentBuilderString("max_in_bytes"); static final XContentBuilderString PEAK_USED = new XContentBuilderString("peak_used"); static final XContentBuilderString PEAK_USED_IN_BYTES = new XContentBuilderString("peak_used_in_bytes"); static final XContentBuilderString PEAK_MAX = new XContentBuilderString("peak_max"); static final XContentBuilderString PEAK_MAX_IN_BYTES = new XContentBuilderString("peak_max_in_bytes"); static final XContentBuilderString GC_COLLECTORS = new XContentBuilderString("gc_collectors"); static final XContentBuilderString GC = new XContentBuilderString("gc"); static final XContentBuilderString COLLECTORS = new XContentBuilderString("collectors"); static final XContentBuilderString COLLECTION_COUNT = new XContentBuilderString("collection_count"); static final XContentBuilderString COLLECTION_TIME = new XContentBuilderString("collection_time"); static final XContentBuilderString COLLECTION_TIME_IN_MILLIS = new XContentBuilderString("collection_time_in_millis"); static final XContentBuilderString BUFFER_POOLS = new XContentBuilderString("buffer_pools"); static final XContentBuilderString TOTAL_CAPACITY = new XContentBuilderString("total_capacity"); static final XContentBuilderString TOTAL_CAPACITY_IN_BYTES = new XContentBuilderString("total_capacity_in_bytes"); static final XContentBuilderString CLASSES = new XContentBuilderString("classes"); static final XContentBuilderString CURRENT_LOADED_COUNT = new XContentBuilderString("current_loaded_count"); static final XContentBuilderString TOTAL_LOADED_COUNT = new XContentBuilderString("total_loaded_count"); static final XContentBuilderString TOTAL_UNLOADED_COUNT = new XContentBuilderString("total_unloaded_count"); } }