# HG changeset patch # User egahlin # Date 1569850556 -7200 # Node ID d284ff23fa4cdacece04fd6d138ab9424e8e47ac # Parent 1211070f439daba7f126ef541ffd4c0608d6f3c9 Remove test applications diff -r 1211070f439d -r d284ff23fa4c src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStart.java --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStart.java Mon Sep 30 15:24:49 2019 +0200 +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStart.java Mon Sep 30 15:35:56 2019 +0200 @@ -234,20 +234,6 @@ print("Use jcmd " + getPid() + " JFR." + cmd + " " + recordingspecifier + " " + fileOption + "to copy recording data to file."); println(); } - if ("monitor".equals(name)) { - try { - Monitor.start(); - } catch (IOException e) { - throw new DCmdException("COuld not start monitor", e); - } - } - if ("health".equals(name)) { - try { - Health.start(); - } catch (Exception e) { - throw new DCmdException("Could not start healt", e); - } - } return getResult(); } diff -r 1211070f439d -r d284ff23fa4c src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/Health.java --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/Health.java Mon Sep 30 15:24:49 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,621 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package jdk.jfr.internal.dcmd; -import java.time.Duration; -import java.time.Instant; -import java.time.LocalDateTime; -import java.time.ZoneOffset; -import java.time.format.DateTimeFormatter; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.StringJoiner; - -import jdk.jfr.consumer.RecordedEvent; -import jdk.jfr.consumer.RecordedFrame; -import jdk.jfr.consumer.RecordedMethod; -import jdk.jfr.consumer.RecordedStackTrace; -import jdk.jfr.consumer.RecordingStream; - -// TODO: This file is to be deleted before integration - -/** - * - * HEALTH REPORT - * - * Example agent that shows how event streaming can be used to gather statistics - * of a running application. - * - * Usage: - * - * $ java -javaagent:health-report.jar[=interval=] MyApp - * - * where interval is how often statistics should be written to standard out. - * - * Example, - * - * $ java -javaagent:health-report.jar MyApp - * - * For testing purposes it is also possible to just run Main.java and it will - * run an allocation loop - * - * $ java Main.java - * - */ -public final class Health { - - private static final String TEMPLATE = - "=================== HEALTH REPORT === $FLUSH_TIME ====================\n" + - "| GC: $GC_NAME Phys. memory: $PHYSIC_MEM Alloc Rate: $ALLOC_RATE |\n" + - "| OC Count : $OC_COUNT Initial Heap: $INIT_HEAP Total Alloc: $TOT_ALLOC |\n" + - "| OC Pause Avg: $OC_AVG Used Heap : $USED_HEAP Thread Count: $THREADS |\n" + - "| OC Pause Max: $OC_MAX Commit. Heap: $COM_HEAP Class Count : $CLASSES |\n" + - "| YC Count : $YC_COUNT CPU Machine : $MACH_CPU Safepoints: $SAFEPOINTS |\n" + - "| YC Pause Avg: $YC_AVG CPU JVM User : $USR_CPU Max Safepoint: $MAX_SAFE |\n" + - "| YC Pause Max: $YC_MAX CPU JVM System: $SYS_CPU Max Comp. Time: $MAX_COM |\n" + - "|--- Top Allocation Methods ------------------------------- -----------------|\n" + - "| $ALLOCACTION_TOP_FRAME $AL_PE |\n" + - "| $ALLOCACTION_TOP_FRAME $AL_PE |\n" + - "| $ALLOCACTION_TOP_FRAME $AL_PE |\n" + - "| $ALLOCACTION_TOP_FRAME $AL_PE |\n" + - "| $ALLOCACTION_TOP_FRAME $AL_PE |\n" + - "|--- Hot Methods ------------------------------------------------------------|\n" + - "| $EXECUTION_TOP_FRAME $EX_PE |\n" + - "| $EXECUTION_TOP_FRAME $EX_PE |\n" + - "| $EXECUTION_TOP_FRAME $EX_PE |\n" + - "| $EXECUTION_TOP_FRAME $EX_PE |\n" + - "| $EXECUTION_TOP_FRAME $EX_PE |\n" + - "==============================================================================\n"; - - public final static Field FLUSH_TIME = new Field(); - - public final static Field GC_NAME = new Field(); - public final static Field OC_COUNT= new Field(Option.COUNT); - public final static Field OC_AVG = new Field(Option.AVERAGE, Option.DURATION); - public final static Field OC_MAX = new Field(Option.MAX, Option.DURATION); - public final static Field YC_COUNT = new Field(Option.COUNT); - public final static Field YC_AVG = new Field(Option.AVERAGE, Option.DURATION); - public final static Field YC_MAX= new Field(Option.MAX, Option.DURATION); - - public final static Field PHYSIC_MEM = new Field(Option.BYTES); - public final static Field INIT_HEAP = new Field(Option.BYTES); - public final static Field USED_HEAP = new Field(Option.BYTES); - public final static Field COM_HEAP = new Field(Option.BYTES); - public final static Field MACH_CPU = new Field(Option.PERCENTAGE); - public final static Field USR_CPU= new Field(Option.PERCENTAGE); - public final static Field SYS_CPU = new Field(Option.PERCENTAGE); - - public final static Field ALLOC_RATE = new Field(Option.BYTES_PER_SECOND); - public final static Field TOT_ALLOC = new Field(Option.TOTAL, Option.BYTES); - public final static Field THREADS = new Field(); - public final static Field CLASSES = new Field(); - public final static Field SAFEPOINTS = new Field(Option.COUNT); - public final static Field MAX_SAFE = new Field(Option.MAX, Option.DURATION); - public final static Field MAX_COM = new Field(Option.MAX, Option.DURATION); - - public final static Field ALLOCACTION_TOP_FRAME = new Field(); - public final static Field AL_PE = new Field(Option.NORMALIZED, Option.TOTAL); - - public final static Field EXECUTION_TOP_FRAME = new Field(); - public final static Field EX_PE = new Field(Option.NORMALIZED, Option.COUNT); - - private static RecordingStream rs; - - public static void start() { - Duration duration = Duration.ofSeconds(1); - - rs = new RecordingStream(); - // Event configuration - rs.enable("jdk.CPULoad").withPeriod(duration); - rs.enable("jdk.YoungGarbageCollection").withoutThreshold(); - rs.enable("jdk.OldGarbageCollection").withoutThreshold(); - rs.enable("jdk.GCHeapSummary").withPeriod(duration); - rs.enable("jdk.PhysicalMemory").withPeriod(duration); - rs.enable("jdk.GCConfiguration").withPeriod(duration); - rs.enable("jdk.SafepointBegin"); - rs.enable("jdk.SafepointEnd"); - rs.enable("jdk.ObjectAllocationOutsideTLAB").withStackTrace(); - rs.enable("jdk.ObjectAllocationInNewTLAB").withStackTrace(); - rs.enable("jdk.ExecutionSample").withPeriod(Duration.ofMillis(10)).withStackTrace(); - rs.enable("jdk.JavaThreadStatistics").withPeriod(duration); - rs.enable("jdk.ClassLoadingStatistics").withPeriod(duration); - rs.enable("jdk.Compilation").withoutThreshold(); - rs.enable("jdk.GCHeapConfiguration").withPeriod(duration); - rs.enable("jdk.Flush").withoutThreshold(); - - // Dispatch handlers - rs.onEvent("jdk.CPULoad", Health::onCPULoad); - rs.onEvent("jdk.YoungGarbageCollection", Health::onYoungColletion); - rs.onEvent("jdk.OldGarbageCollection", Health::onOldCollection); - rs.onEvent("jdk.GCHeapSummary", Health::onGCHeapSummary); - rs.onEvent("jdk.PhysicalMemory", Health::onPhysicalMemory); - rs.onEvent("jdk.GCConfiguration", Health::onGCConfiguration); - rs.onEvent("jdk.SafepointBegin", Health::onSafepointBegin); - rs.onEvent("jdk.SafepointEnd", Health::onSafepointEnd); - rs.onEvent("jdk.ObjectAllocationOutsideTLAB", Health::onObjectAllocationOutsideTLAB); - rs.onEvent("jdk.ObjectAllocationInNewTLAB", Health::onObjectAllocationInNewTLAB); - rs.onEvent("jdk.ExecutionSample", Health::onExecutionSample); - rs.onEvent("jdk.JavaThreadStatistics", Health::onJavaThreadStatistics); - rs.onEvent("jdk.ClassLoadingStatistics", Health::onClassLoadingStatistics); - rs.onEvent("jdk.Compilation", Health::onCompilation); - rs.onEvent("jdk.GCHeapConfiguration", Health::onGCHeapConfiguration); - rs.onEvent("jdk.Flush", Health::onFlushpoint); - - rs.onFlush(Health::printReport); - rs.startAsync(); - System.out.println("Health started"); - } - - private static void onCPULoad(RecordedEvent event) { - MACH_CPU.addSample(event.getDouble("machineTotal")); - SYS_CPU.addSample(event.getDouble("jvmSystem")); - USR_CPU.addSample(event.getDouble("jvmUser")); - } - - private static void onYoungColletion(RecordedEvent event) { - long nanos = event.getDuration().toNanos(); - YC_COUNT.addSample(nanos); - YC_MAX.addSample(nanos); - YC_AVG.addSample(nanos); - } - - private static void onOldCollection(RecordedEvent event) { - long nanos = event.getDuration().toNanos(); - OC_COUNT.addSample(nanos); - OC_MAX.addSample(nanos); - OC_AVG.addSample(nanos); - } - - private static void onGCHeapSummary(RecordedEvent event) { - USED_HEAP.addSample(event.getLong("heapUsed")); - COM_HEAP.addSample(event.getLong("heapSpace.committedSize")); - } - - private static void onPhysicalMemory(RecordedEvent event) { - PHYSIC_MEM.addSample(event.getLong("totalSize")); - } - - private static void onCompilation(RecordedEvent event) { - MAX_COM.addSample(event.getDuration().toNanos()); - } - - private static void onGCConfiguration(RecordedEvent event) { - String gc = event.getString("oldCollector"); - String yc = event.getString("youngCollector"); - if (yc != null) { - gc += "/" + yc; - } - GC_NAME.addSample(gc); - } - - private final static Map safepointBegin = new HashMap<>(); - - private static void onSafepointBegin(RecordedEvent event) { - safepointBegin.put(event.getValue("safepointId"), event.getEndTime()); - } - - private static void onSafepointEnd(RecordedEvent event) { - long id = event.getValue("safepointId"); - Instant begin = safepointBegin.get(id); - if (begin != null) { - long nanos = Duration.between(begin, event.getEndTime()).toNanos(); - safepointBegin.remove(id); - SAFEPOINTS.addSample(nanos); - MAX_SAFE.addSample(nanos); - } - } - - private static void onObjectAllocationOutsideTLAB(RecordedEvent event) { - onAllocationSample(event, event.getLong("allocationSize")); - } - - private static void onObjectAllocationInNewTLAB(RecordedEvent event) { - onAllocationSample(event, event.getLong("tlabSize")); - } - - private static double totalAllocated; - private static long firstAllocationTime = -1; - private static void onAllocationSample(RecordedEvent event, long size) { - String topFrame = topFrame(event.getStackTrace()); - if (topFrame != null) { - ALLOCACTION_TOP_FRAME.addSample(topFrame, size); - AL_PE.addSample(topFrame, size); - } - TOT_ALLOC.addSample(size); - // ALLOC_RATE.addRate(timetsamp, amount); - long timestamp = event.getEndTime().toEpochMilli(); - totalAllocated += size; - if (firstAllocationTime > 0) { - long elapsedTime = timestamp - firstAllocationTime; - if (elapsedTime > 0) { - double rate = 1000.0 * (totalAllocated / elapsedTime); - ALLOC_RATE.addSample(rate); - } - } else { - firstAllocationTime = timestamp; - } - } - - private static void onExecutionSample(RecordedEvent event) { - String topFrame = topFrame(event.getStackTrace()); - EXECUTION_TOP_FRAME.addSample(topFrame, 1); - EX_PE.addSample(topFrame, 1); - } - - private static void onJavaThreadStatistics(RecordedEvent event) { - THREADS.addSample(event.getDouble("activeCount")); - } - - private static void onClassLoadingStatistics(RecordedEvent event) { - long diff = event.getLong("loadedClassCount") - event.getLong("unloadedClassCount"); - CLASSES.addSample(diff); - } - - private static void onGCHeapConfiguration(RecordedEvent event) { - INIT_HEAP.addSample(event.getLong("initialSize")); - } - - private final static DateTimeFormatter FORMATTER = - DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); - private static void onFlushpoint(RecordedEvent event) { - Instant i = event.getEndTime(); - LocalDateTime l = LocalDateTime.ofInstant(i, ZoneOffset.systemDefault()); - FLUSH_TIME.addSample(FORMATTER.format(l)); - } - - // # # # TEMPLATE AND SAMPLING # # # - - private enum Option { - BYTES, PERCENTAGE, DURATION, BYTES_PER_SECOND, NORMALIZED, COUNT, AVERAGE, TOTAL, MAX - } - - private static final class Record { - private final Object key; - private int count = 1; - private double total; - private double max; - private Object value = null; - public Record(Object key, String sample) { - this.key = key; - this.value = sample; - } - - public Record(Object object, double sample) { - this.key = object; - this.value = sample; - this.max = sample; - this.total = sample; - } - - public long getCount() { - return count; - } - - public double getAverage() { - return total / count; - } - - public double getMax() { - return max; - } - - public double getTotal() { - return total; - } - - public int hashCode() { - return key == null ? 0 : key.hashCode(); - } - - public boolean equals(Object o) { - if (o instanceof Record) { - Record that = (Record) o; - return Objects.equals(that.key, this.key); - } - return false; - } - } - - private static final class Field implements Iterable { - private final HashMap histogram = new HashMap<>(); - private final Option[] options; - private double norm; - - public Field(Option... options) { - this.options = options; - } - - public void addSample(double sample) { - addSample(this, sample); - } - - public void addSample(String sample) { - histogram.merge(this, new Record(this, sample), (a, b) -> { - a.count++; - a.value = sample; - return a; - }); - } - - public void addSample(Object key, double sample) { - histogram.merge(key, new Record(key, sample), (a, b) -> { - a.count++; - a.total += sample; - a.value = sample; - a.max = Math.max(a.max, sample); - return a; - }); - } - - public boolean hasOption(Option option) { - for (Option o : options) { - if (o == option) { - return true; - } - } - return false; - } - - @Override - public Iterator iterator() { - List records = new ArrayList<>(histogram.values()); - Collections.sort(records, (a, b) -> Long.compare(b.getCount(), a.getCount())); - if (hasOption(Option.TOTAL)) { - Collections.sort(records, (a, b) -> Double.compare(b.getTotal(), a.getTotal())); - } - if (hasOption(Option.NORMALIZED)) { - norm = 0.0; - for (Record r : records) { - if (hasOption(Option.TOTAL)) { - norm += r.getTotal(); - } - if (hasOption(Option.COUNT)) { - norm += r.getCount(); - } - } - } - return records.iterator(); - } - - public double getNorm() { - return norm; - } - } - - private static void printReport() { - try { - StringBuilder template = new StringBuilder(TEMPLATE); - for (java.lang.reflect.Field f : Health.class.getDeclaredFields()) { - String variable = "$" + f.getName(); - if (f.getType() == Field.class) { - writeParam(template, variable, (Field) f.get(null)); - } - } - System.out.println(template.toString()); - } catch (Exception e) { - e.printStackTrace(); - } - } - - private static void writeParam(StringBuilder template, String variable, Field param) { - Iterator it = param.iterator(); - int lastIndex = 0; - while (true) { - int index = template.indexOf(variable, lastIndex); - if (index == -1) { - return; - } - lastIndex = index + 1; - Record record = it.hasNext() ? it.next() : null; - Object value = null; - if (record != null) { - value = (record.key == param) ? record.value : record.key; - } - if (value != null) { - if (param.hasOption(Option.MAX)) { - value = record.getMax(); - } - if (param.hasOption(Option.COUNT)) { - value = record.getCount(); - } - if (param.hasOption(Option.AVERAGE)) { - value = record.getAverage(); - } - if (param.hasOption(Option.TOTAL)) { - value = record.getTotal(); - } - } - if (param.hasOption(Option.COUNT)) { - value = value == null ? 0 : value; - } - if (param.hasOption(Option.BYTES)) { - value = formatBytes((Number) value); - } - if (param.hasOption(Option.DURATION)) { - value = formatDuration((Number) value); - } - if (param.hasOption(Option.BYTES_PER_SECOND)) { - if (value != null) { - value = formatBytes((Number) value) + "/s"; - } - } - if (param.hasOption(Option.NORMALIZED)) { - if (value != null) { - double d = ((Number) value).doubleValue() / param.getNorm(); - value = formatPercentage(d); - } - } - if (param.hasOption(Option.PERCENTAGE)) { - value = formatPercentage((Number) value); - } - String text; - if (value == null) { - text = record == null ? "" : "N/A"; - } else { - text = String.valueOf(value); - } - int length = Math.max(text.length(), variable.length()); - for (int i = 0; i < length; i++) { - char c = i < text.length() ? text.charAt(i) : ' '; - template.setCharAt(index + i, c); - } - } - } - - // # # # FORMATTING # # # - - enum TimespanUnit { - NANOSECONDS("ns", 1000), MICROSECONDS("us", 1000), MILLISECONDS("ms", 1000), SECONDS("s", 60), MINUTES("m", 60), - HOURS("h", 24), DAYS("d", 7); - - final String text; - final long amount; - - TimespanUnit(String unit, long amount) { - this.text = unit; - this.amount = amount; - } - } - - private static String formatDuration(Number value) { - if (value == null) { - return "N/A"; - } - double t = value.doubleValue(); - TimespanUnit result = TimespanUnit.NANOSECONDS; - for (TimespanUnit unit : TimespanUnit.values()) { - result = unit; - if (t < 1000) { - break; - } - t = t / unit.amount; - } - return String.format("%.1f %s", t, result.text); - } - - private static String formatPercentage(Number value) { - if (value == null) { - return "N/A"; - } - return String.format("%6.2f %%", value.doubleValue() * 100); - } - - private static String formatBytes(Number value) { - if (value == null) { - return "N/A"; - } - long bytes = value.longValue(); - if (bytes >= 1024 * 1024l) { - return bytes / (1024 * 1024L) + " MB"; - } - if (bytes >= 1024) { - return bytes / 1024 + " kB"; - } - return bytes + " bytes"; - } - - private static String topFrame(RecordedStackTrace stackTrace) { - if (stackTrace == null) { - return null; - } - List frames = stackTrace.getFrames(); - if (!frames.isEmpty()) { - RecordedFrame topFrame = frames.get(0); - if (topFrame.isJavaFrame()) { - return formatMethod(topFrame.getMethod()); - } - } - return null; - } - - private static String formatMethod(RecordedMethod m) { - StringBuilder sb = new StringBuilder(); - String typeName = m.getType().getName(); - typeName = typeName.substring(typeName.lastIndexOf('.') + 1); - sb.append(typeName).append(".").append(m.getName()); - sb.append("("); - StringJoiner sj = new StringJoiner(", "); - String md = m.getDescriptor().replace("/", "."); - String parameter = md.substring(1, md.lastIndexOf(")")); - for (String qualifiedName : decodeDescriptors(parameter)) { - sj.add(qualifiedName.substring(qualifiedName.lastIndexOf('.') + 1)); - } - sb.append(sj.length() > 10 ? "..." : sj); - sb.append(")"); - return sb.toString(); - } - - private static List decodeDescriptors(String descriptor) { - List descriptors = new ArrayList<>(); - for (int index = 0; index < descriptor.length(); index++) { - String arrayBrackets = ""; - while (descriptor.charAt(index) == '[') { - arrayBrackets += "[]"; - index++; - } - char c = descriptor.charAt(index); - String type; - switch (c) { - case 'L': - int endIndex = descriptor.indexOf(';', index); - type = descriptor.substring(index + 1, endIndex); - index = endIndex; - break; - case 'I': - type = "int"; - break; - case 'J': - type = "long"; - break; - case 'Z': - type = "boolean"; - break; - case 'D': - type = "double"; - break; - case 'F': - type = "float"; - break; - case 'S': - type = "short"; - break; - case 'C': - type = "char"; - break; - case 'B': - type = "byte"; - break; - default: - type = ""; - } - descriptors.add(type + arrayBrackets); - } - return descriptors; - } -} - diff -r 1211070f439d -r d284ff23fa4c src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/Monitor.java --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/Monitor.java Mon Sep 30 15:24:49 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package jdk.jfr.internal.dcmd; - -import java.io.IOException; - -import jdk.jfr.consumer.EventStream; -import jdk.jfr.consumer.RecordingStream; - -// TODO: This file is to be deleted before integration - -public class Monitor { - - private static EventStream stream; - - public static void start() throws IOException { - stream = new RecordingStream(); - stream.startAsync(); - System.out.println("Monitor started"); - } -}