mirror of
https://github.com/openjdk/jdk.git
synced 2026-04-19 19:30:51 +00:00
8214896: JFR Tool left files behind
Reviewed-by: mgronlun
This commit is contained in:
parent
9b6ea802b5
commit
69f0bf41d9
@ -1,150 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2018, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.cmd;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Deque;
|
||||
import java.util.List;
|
||||
|
||||
abstract class Command {
|
||||
|
||||
private final static Command HELP = new HelpCommand();
|
||||
private final static List<Command> COMMANDS = createCommands();
|
||||
|
||||
static void displayHelp() {
|
||||
System.out.println("Usage: java " + Execute.class.getName() + " <command> [<options>]");
|
||||
System.out.println();
|
||||
displayAvailableCommands();
|
||||
}
|
||||
|
||||
static void displayAvailableCommands() {
|
||||
System.out.println("Available commands are:");
|
||||
System.out.println();
|
||||
boolean first = true;
|
||||
for (Command c : Command.COMMANDS) {
|
||||
if (!first) {
|
||||
System.out.println();
|
||||
}
|
||||
System.out.println(" " + c.getName() + " " + c.getOptionSyntax());
|
||||
System.out.println(" " + c.getDescription());
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
|
||||
public static List<Command> getCommands() {
|
||||
return COMMANDS;
|
||||
}
|
||||
|
||||
public static Command valueOf(String commandName) {
|
||||
for (Command command : COMMANDS) {
|
||||
if (command.getName().equals(commandName)) {
|
||||
return command;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
abstract public String getOptionSyntax();
|
||||
|
||||
abstract public String getName();
|
||||
|
||||
abstract public String getDescription();
|
||||
|
||||
abstract public void displayOptionUsage();
|
||||
|
||||
abstract public void execute(Deque<String> options);
|
||||
|
||||
final protected void userFailed(String message) {
|
||||
println();
|
||||
println(message);
|
||||
displayUsage();
|
||||
throw new IllegalArgumentException(message);
|
||||
}
|
||||
|
||||
final protected void ensureMaxArgumentCount(Deque<String> options, int maxCount) {
|
||||
if (options.size() > maxCount) {
|
||||
userFailed("Too many arguments");
|
||||
}
|
||||
}
|
||||
|
||||
final protected void ensureMinArgumentCount(Deque<String> options, int minCount) {
|
||||
if (options.size() < minCount) {
|
||||
userFailed("Too few arguments");
|
||||
}
|
||||
}
|
||||
|
||||
final protected void ensureFileExist(Path file) {
|
||||
if (!Files.exists(file)) {
|
||||
userFailed("Could not find file " + file);
|
||||
}
|
||||
}
|
||||
|
||||
final protected Path ensureFileDoesNotExist(Path file) {
|
||||
if (Files.exists(file)) {
|
||||
userFailed("File " + file + " already exists");
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
final protected void ensureJFRFile(Path path) {
|
||||
if (!path.toString().endsWith(".jfr")) {
|
||||
userFailed("Filename must end with .jfr");
|
||||
}
|
||||
}
|
||||
|
||||
final protected void displayUsage() {
|
||||
String javaText = "java " + Execute.class.getName();
|
||||
println();
|
||||
println("Usage: " + javaText + " " + getName() + " " + getOptionSyntax());
|
||||
println();
|
||||
displayOptionUsage();
|
||||
}
|
||||
|
||||
final protected void println() {
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
final protected void print(String text) {
|
||||
System.out.print(text);
|
||||
}
|
||||
|
||||
final protected void println(String text) {
|
||||
System.out.println(text);
|
||||
}
|
||||
|
||||
private static List<Command> createCommands() {
|
||||
List<Command> commands = new ArrayList<>();
|
||||
commands.add(new PrintCommand());
|
||||
commands.add(new SummaryCommand());
|
||||
commands.add(new ReconstructCommand());
|
||||
commands.add(new SplitCommand());
|
||||
commands.add(HELP);
|
||||
return Collections.unmodifiableList(commands);
|
||||
}
|
||||
}
|
||||
@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2018, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.cmd;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Deque;
|
||||
import java.util.LinkedList;
|
||||
|
||||
/**
|
||||
* Launcher class for JFR tools
|
||||
*
|
||||
*/
|
||||
public final class Execute {
|
||||
|
||||
public static void main(String... args) {
|
||||
Deque<String> argList = new LinkedList<>(Arrays.asList(args));
|
||||
if (argList.isEmpty()) {
|
||||
System.out.println();
|
||||
Command.displayHelp();
|
||||
return;
|
||||
}
|
||||
String command = argList.remove();
|
||||
for (Command c : Command.getCommands()) {
|
||||
if (c.getName().equals(command)) {
|
||||
try {
|
||||
c.execute(argList);
|
||||
} catch (IllegalArgumentException iae) {
|
||||
return; // already handled by command
|
||||
} catch (Throwable e) {
|
||||
System.out.println();
|
||||
System.out.println(e.getMessage());
|
||||
System.out.println();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
System.out.println();
|
||||
System.out.println("Unknown command " + command + ".");
|
||||
System.out.println();
|
||||
Command.displayHelp();
|
||||
}
|
||||
}
|
||||
@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2018, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.cmd;
|
||||
|
||||
import java.util.Deque;
|
||||
|
||||
final class HelpCommand extends Command {
|
||||
|
||||
@Override
|
||||
public String getOptionSyntax() {
|
||||
return "[<command>]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayOptionUsage() {
|
||||
println(" <command> The name of the command to get help for");
|
||||
println();
|
||||
Command.displayAvailableCommands();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "help";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Display help about a command";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Deque<String> options) {
|
||||
if (options.isEmpty()) {
|
||||
displayUsage();
|
||||
} else {
|
||||
ensureMaxArgumentCount(options, 1);
|
||||
String commandName = options.remove();
|
||||
Command c = Command.valueOf(commandName);
|
||||
if (c == null) {
|
||||
userFailed("Unknown command " + commandName);
|
||||
}
|
||||
c.displayUsage();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,258 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2018, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.cmd;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import jdk.jfr.EventType;
|
||||
import jdk.jfr.ValueDescriptor;
|
||||
import jdk.jfr.consumer.RecordedEvent;
|
||||
import jdk.jfr.consumer.RecordedObject;
|
||||
import jdk.jfr.consumer.RecordingFile;
|
||||
|
||||
final class JSONWriter extends StructuredWriter {
|
||||
|
||||
public JSONWriter(PrintWriter writer) {
|
||||
super(writer);
|
||||
}
|
||||
|
||||
public void print(Path source) throws IOException {
|
||||
try (RecordingFile es = new RecordingFile(source)) {
|
||||
printObjectBegin();
|
||||
printRecording(es);
|
||||
printObjectEnd();
|
||||
flush();
|
||||
}
|
||||
}
|
||||
|
||||
private void printRecording(RecordingFile es) throws IOException {
|
||||
printDataStructureName("recording");
|
||||
printObjectBegin();
|
||||
printEvents(es);
|
||||
printObjectEnd();
|
||||
}
|
||||
|
||||
private void printEvents(RecordingFile es) throws IOException {
|
||||
printDataStructureName("events");
|
||||
printArrayBegin();
|
||||
boolean first = true;
|
||||
while (es.hasMoreEvents()) {
|
||||
RecordedEvent e = es.readEvent();
|
||||
printNewDataStructure(first, true, null);
|
||||
printEvent(e);
|
||||
flush();
|
||||
first = false;
|
||||
}
|
||||
printArrayEnd();
|
||||
}
|
||||
|
||||
private void printEvent(RecordedEvent e) {
|
||||
printObjectBegin();
|
||||
EventType type = e.getEventType();
|
||||
printValue(true, false, "name", type.getName());
|
||||
printValue(false, false, "typeId", type.getId());
|
||||
printValue(false, false, "startTime", e.getStartTime());
|
||||
printValue(false, false, "duration", e.getDuration());
|
||||
printNewDataStructure(false, false, "values");
|
||||
printObject(e);
|
||||
printObjectEnd();
|
||||
}
|
||||
|
||||
void printValue(boolean first, boolean arrayElement, String name, Object value) {
|
||||
printNewDataStructure(first, arrayElement, name);
|
||||
if (!printIfNull(value)) {
|
||||
if (value instanceof Boolean) {
|
||||
printAsString(value);
|
||||
return;
|
||||
}
|
||||
if (value instanceof Double) {
|
||||
Double dValue = (Double) value;
|
||||
if (Double.isNaN(dValue) || Double.isInfinite(dValue)) {
|
||||
printNull();
|
||||
return;
|
||||
}
|
||||
printAsString(value);
|
||||
return;
|
||||
}
|
||||
if (value instanceof Float) {
|
||||
Float fValue = (Float) value;
|
||||
if (Float.isNaN(fValue) || Float.isInfinite(fValue)) {
|
||||
printNull();
|
||||
return;
|
||||
}
|
||||
printAsString(value);
|
||||
return;
|
||||
}
|
||||
if (value instanceof Number) {
|
||||
printAsString(value);
|
||||
return;
|
||||
}
|
||||
print("\"");
|
||||
printEscaped(String.valueOf(value));
|
||||
print("\"");
|
||||
}
|
||||
}
|
||||
|
||||
public void printObject(RecordedObject object) {
|
||||
printObjectBegin();
|
||||
boolean first = true;
|
||||
for (ValueDescriptor v : object.getFields()) {
|
||||
printValueDescriptor(first, false, v, object.getValue(v.getName()));
|
||||
first = false;
|
||||
}
|
||||
printObjectEnd();
|
||||
}
|
||||
|
||||
private void printArray(ValueDescriptor v, Object[] array) {
|
||||
printArrayBegin();
|
||||
boolean first = true;
|
||||
for (Object arrayElement : array) {
|
||||
printValueDescriptor(first, true, v, arrayElement);
|
||||
first = false;
|
||||
}
|
||||
printArrayEnd();
|
||||
}
|
||||
|
||||
private void printValueDescriptor(boolean first, boolean arrayElement, ValueDescriptor vd, Object value) {
|
||||
if (vd.isArray() && !arrayElement) {
|
||||
printNewDataStructure(first, arrayElement, vd.getName());
|
||||
if (!printIfNull(value)) {
|
||||
printArray(vd, (Object[]) value);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!vd.getFields().isEmpty()) {
|
||||
printNewDataStructure(first, arrayElement, vd.getName());
|
||||
if (!printIfNull(value)) {
|
||||
printObject((RecordedObject) value);
|
||||
}
|
||||
return;
|
||||
}
|
||||
printValue(first, arrayElement, vd.getName(), value);
|
||||
}
|
||||
|
||||
private void printNewDataStructure(boolean first, boolean arrayElement, String name) {
|
||||
if (!first) {
|
||||
print(", ");
|
||||
if (!arrayElement) {
|
||||
println();
|
||||
}
|
||||
}
|
||||
if (!arrayElement) {
|
||||
printDataStructureName(name);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean printIfNull(Object value) {
|
||||
if (value == null) {
|
||||
printNull();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void printNull() {
|
||||
print("null");
|
||||
}
|
||||
|
||||
private void printDataStructureName(String text) {
|
||||
printIndent();
|
||||
print("\"");
|
||||
print(text);
|
||||
print("\": ");
|
||||
}
|
||||
|
||||
private void printObjectEnd() {
|
||||
retract();
|
||||
println();
|
||||
printIndent();
|
||||
print("}");
|
||||
}
|
||||
|
||||
private void printObjectBegin() {
|
||||
println("{");
|
||||
indent();
|
||||
}
|
||||
|
||||
private void printArrayEnd() {
|
||||
print("]");
|
||||
}
|
||||
|
||||
private void printArrayBegin() {
|
||||
print("[");
|
||||
}
|
||||
|
||||
private void printEscaped(String text) {
|
||||
for (int i = 0; i < text.length(); i++) {
|
||||
printEscaped(text.charAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
private void printEscaped(char c) {
|
||||
if (c == '\b') {
|
||||
print("\\b");
|
||||
return;
|
||||
}
|
||||
if (c == '\n') {
|
||||
print("\\n");
|
||||
return;
|
||||
}
|
||||
if (c == '\t') {
|
||||
print("\\t");
|
||||
return;
|
||||
}
|
||||
if (c == '\f') {
|
||||
print("\\f");
|
||||
return;
|
||||
}
|
||||
if (c == '\r') {
|
||||
print("\\r");
|
||||
return;
|
||||
}
|
||||
if (c == '\"') {
|
||||
print("\\\"");
|
||||
return;
|
||||
}
|
||||
if (c == '\\') {
|
||||
print("\\\\");
|
||||
return;
|
||||
}
|
||||
if (c == '/') {
|
||||
print("\\/");
|
||||
return;
|
||||
}
|
||||
if (c > 0x7F || c < 32) {
|
||||
print("\\u");
|
||||
// 0x10000 will pad with zeros.
|
||||
print(Integer.toHexString(0x10000 + (int) c).substring(1));
|
||||
return;
|
||||
}
|
||||
print(c);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,236 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2018, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.cmd;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
import jdk.jfr.AnnotationElement;
|
||||
import jdk.jfr.ValueDescriptor;
|
||||
import jdk.jfr.consumer.RecordedEvent;
|
||||
import jdk.jfr.consumer.RecordedObject;
|
||||
import jdk.jfr.consumer.RecordingFile;
|
||||
import jdk.jfr.internal.PrivateAccess;
|
||||
import jdk.jfr.internal.Type;
|
||||
import jdk.jfr.internal.consumer.ChunkHeader;
|
||||
import jdk.jfr.internal.consumer.RecordingInput;
|
||||
|
||||
public final class PrettyWriter extends StructuredWriter {
|
||||
|
||||
public PrettyWriter(PrintWriter destination) {
|
||||
super(destination);
|
||||
}
|
||||
|
||||
void print(Path source) throws FileNotFoundException, IOException {
|
||||
try (RecordingInput input = new RecordingInput(source.toFile())) {
|
||||
HashSet<Type> typeSet = new HashSet<>();
|
||||
for (ChunkHeader ch = new ChunkHeader(input); !ch.isLastChunk(); ch = ch.nextHeader()) {
|
||||
typeSet.addAll(ch.readMetadata().getTypes());
|
||||
}
|
||||
List<Type> types = new ArrayList<>(typeSet);
|
||||
Collections.sort(types, (c1, c2) -> Long.compare(c1.getId(), c2.getId()));
|
||||
for (Type t : types) {
|
||||
printType(t);
|
||||
}
|
||||
flush();
|
||||
}
|
||||
|
||||
try (RecordingFile es = new RecordingFile(source)) {
|
||||
while (es.hasMoreEvents()) {
|
||||
print(es.readEvent());
|
||||
flush();
|
||||
}
|
||||
}
|
||||
flush();
|
||||
}
|
||||
|
||||
public void printType(Type t) throws IOException {
|
||||
print("// id: ");
|
||||
println(String.valueOf(t.getId()));
|
||||
int commentIndex = t.getName().length() + 10;
|
||||
String typeName = t.getName();
|
||||
int index = typeName.lastIndexOf(".");
|
||||
if (index != -1) {
|
||||
println("package " + typeName.substring(0, index) + ";");
|
||||
}
|
||||
printAnnotations(commentIndex, t.getAnnotationElements());
|
||||
print("class " + typeName.substring(index + 1));
|
||||
String superType = t.getSuperType();
|
||||
if (superType != null) {
|
||||
print(" extends " + superType);
|
||||
}
|
||||
println(" {");
|
||||
indent();
|
||||
for (ValueDescriptor v : t.getFields()) {
|
||||
printField(commentIndex, v);
|
||||
}
|
||||
retract();
|
||||
println("}");
|
||||
println();
|
||||
}
|
||||
|
||||
private void printField(int commentIndex, ValueDescriptor v) throws IOException {
|
||||
println();
|
||||
printAnnotations(commentIndex, v.getAnnotationElements());
|
||||
printIndent();
|
||||
Type vType = PrivateAccess.getInstance().getType(v);
|
||||
if (Type.SUPER_TYPE_SETTING.equals(vType.getSuperType())) {
|
||||
print("static ");
|
||||
}
|
||||
print(makeSimpleType(v.getTypeName()));
|
||||
if (v.isArray()) {
|
||||
print("[]");
|
||||
}
|
||||
print(" ");
|
||||
print(v.getName());
|
||||
print(";");
|
||||
printCommentRef(commentIndex, v.getTypeId());
|
||||
}
|
||||
|
||||
private void printCommentRef(int commentIndex, long typeId) throws IOException {
|
||||
int column = getColumn();
|
||||
if (column > commentIndex) {
|
||||
print(" ");
|
||||
} else {
|
||||
while (column < commentIndex) {
|
||||
print(" ");
|
||||
column++;
|
||||
}
|
||||
}
|
||||
println(" // id=" + typeId);
|
||||
}
|
||||
|
||||
private void printAnnotations(int commentIndex, List<AnnotationElement> annotations) throws IOException {
|
||||
for (AnnotationElement a : annotations) {
|
||||
printIndent();
|
||||
print("@");
|
||||
print(makeSimpleType(a.getTypeName()));
|
||||
List<ValueDescriptor> vs = a.getValueDescriptors();
|
||||
if (!vs.isEmpty()) {
|
||||
printAnnotation(a);
|
||||
printCommentRef(commentIndex, a.getTypeId());
|
||||
} else {
|
||||
println();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void printAnnotation(AnnotationElement a) throws IOException {
|
||||
StringJoiner sj = new StringJoiner(", ", "(", ")");
|
||||
List<ValueDescriptor> vs = a.getValueDescriptors();
|
||||
for (ValueDescriptor v : vs) {
|
||||
Object o = a.getValue(v.getName());
|
||||
if (vs.size() == 1 && v.getName().equals("value")) {
|
||||
sj.add(textify(o));
|
||||
} else {
|
||||
sj.add(v.getName() + "=" + textify(o));
|
||||
}
|
||||
}
|
||||
print(sj.toString());
|
||||
}
|
||||
|
||||
private String textify(Object o) {
|
||||
if (o.getClass().isArray()) {
|
||||
Object[] array = (Object[]) o;
|
||||
if (array.length == 1) {
|
||||
return quoteIfNeeded(array[0]);
|
||||
}
|
||||
StringJoiner s = new StringJoiner(", ", "{", "}") ;
|
||||
for (Object ob : array) {
|
||||
s.add(quoteIfNeeded(ob));
|
||||
}
|
||||
return s.toString();
|
||||
} else {
|
||||
return quoteIfNeeded(o);
|
||||
}
|
||||
}
|
||||
|
||||
private String quoteIfNeeded(Object o) {
|
||||
if (o instanceof String) {
|
||||
return "\"" + o + "\"";
|
||||
} else {
|
||||
return String.valueOf(o);
|
||||
}
|
||||
}
|
||||
|
||||
private String makeSimpleType(String typeName) {
|
||||
int index = typeName.lastIndexOf(".");
|
||||
return typeName.substring(index + 1);
|
||||
}
|
||||
|
||||
public void print(RecordedEvent event) throws IOException {
|
||||
print(makeSimpleType(event.getEventType().getName()), " ");
|
||||
print((RecordedObject) event, "");
|
||||
}
|
||||
|
||||
public void print(RecordedObject struct, String postFix) throws IOException {
|
||||
println("{");
|
||||
indent();
|
||||
for (ValueDescriptor v : struct.getFields()) {
|
||||
printIndent();
|
||||
print(v.getName(), " = ");
|
||||
printValue(struct.getValue(v.getName()), "");
|
||||
}
|
||||
retract();
|
||||
printIndent();
|
||||
println("}" + postFix);
|
||||
}
|
||||
|
||||
private void printArray(Object[] array) throws IOException {
|
||||
println("[");
|
||||
indent();
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
printIndent();
|
||||
printValue(array[i], i + 1 < array.length ? ", " : "");
|
||||
}
|
||||
retract();
|
||||
printIndent();
|
||||
println("]");
|
||||
}
|
||||
|
||||
private void printValue(Object value, String postFix) throws IOException {
|
||||
if (value == null) {
|
||||
println("null" + postFix);
|
||||
} else if (value instanceof RecordedObject) {
|
||||
print((RecordedObject) value, postFix);
|
||||
} else if (value.getClass().isArray()) {
|
||||
printArray((Object[]) value);
|
||||
} else {
|
||||
String text = String.valueOf(value);
|
||||
if (value instanceof String) {
|
||||
text = "\"" + text + "\"";
|
||||
}
|
||||
println(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,100 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2018, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.cmd;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Deque;
|
||||
|
||||
final class PrintCommand extends Command {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "print";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOptionSyntax() {
|
||||
return "[--xml|--json] <file>";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Print contents of a recording file (.jfr)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayOptionUsage() {
|
||||
println(" --xml Print a recording in XML format");
|
||||
println();
|
||||
println(" --json Print a recording in JSON format");
|
||||
println();
|
||||
println(" <file> Location of the recording file (.jfr) to print");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Deque<String> options) {
|
||||
if (options.isEmpty()) {
|
||||
userFailed("Missing file");
|
||||
}
|
||||
ensureMaxArgumentCount(options, 2);
|
||||
|
||||
Path file = Paths.get(options.removeLast());
|
||||
|
||||
ensureFileExist(file);
|
||||
ensureJFRFile(file);
|
||||
ensureMaxArgumentCount(options, 1);
|
||||
|
||||
String format = "--pretty";
|
||||
if (!options.isEmpty()) {
|
||||
format = options.remove();
|
||||
}
|
||||
try (PrintWriter pw = new PrintWriter(System.out)) {
|
||||
try {
|
||||
switch (format) {
|
||||
case "--pretty":
|
||||
PrettyWriter prettyWriter = new PrettyWriter(pw);
|
||||
prettyWriter.print(file);
|
||||
break;
|
||||
case "--xml":
|
||||
XMLWriter xmlPrinter = new XMLWriter(pw);
|
||||
xmlPrinter.print(file);
|
||||
break;
|
||||
case "--json":
|
||||
JSONWriter jsonWriter = new JSONWriter(pw);
|
||||
jsonWriter.print(file);
|
||||
break;
|
||||
default:
|
||||
userFailed("Unknown option " + format);
|
||||
break;
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
userFailed("Could not read recording at " + file.toAbsolutePath() + ". " + ioe.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,131 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2018, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.cmd;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.file.DirectoryStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Deque;
|
||||
import java.util.List;
|
||||
|
||||
final class ReconstructCommand extends Command {
|
||||
|
||||
@Override
|
||||
public String getOptionSyntax() {
|
||||
return "<repository> <file>";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "reconstruct";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Assemble leftover chunks, from a disk repository, into a recording file (.jfr)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayOptionUsage() {
|
||||
println(" <repository> Directory where the repository is located");
|
||||
println();
|
||||
println(" <file> Name of the recording file (.jfr) to create");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Deque<String> options) {
|
||||
ensureMinArgumentCount(options, 2);
|
||||
ensureMaxArgumentCount(options, 2);
|
||||
|
||||
Path repository = Paths.get(options.pop()).toAbsolutePath();
|
||||
if (!Files.exists(repository)) {
|
||||
userFailed("Could not find disk repository at " + repository);
|
||||
}
|
||||
if (!Files.isDirectory(repository)) {
|
||||
userFailed("Must specify a directory as disk repository");
|
||||
}
|
||||
Path output = Paths.get(options.pop());
|
||||
ensureFileDoesNotExist(output);
|
||||
ensureJFRFile(output);
|
||||
|
||||
try (FileOutputStream fos = new FileOutputStream(output.toFile())) {
|
||||
List<Path> files = listJFRFiles(repository);
|
||||
if (files.isEmpty()) {
|
||||
throw new IllegalStateException("No *.jfr files found at " + repository);
|
||||
}
|
||||
println();
|
||||
println("Combining files... ");
|
||||
println();
|
||||
transferTo(files, output, fos.getChannel());
|
||||
println();
|
||||
println("Reconstruction complete.");
|
||||
} catch (IOException e) {
|
||||
userFailed("Could not open destination file " + output + ". " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private List<Path> listJFRFiles(Path path) throws IOException {
|
||||
try {
|
||||
List<Path> files = new ArrayList<>();
|
||||
if (Files.isDirectory(path)) {
|
||||
try (DirectoryStream<Path> stream = Files.newDirectoryStream(path, "*.jfr")) {
|
||||
for (Path p : stream) {
|
||||
if (!Files.isDirectory(p) && Files.isReadable(p)) {
|
||||
files.add(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
files.sort((u, v) -> u.getFileName().compareTo(v.getFileName()));
|
||||
return files;
|
||||
} catch (IOException ioe) {
|
||||
throw new IllegalStateException("Could not list *.jfr for directory " + path + ". " + ioe.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void transferTo(List<Path> sourceFiles, Path output, FileChannel out) {
|
||||
long pos = 0;
|
||||
for (Path p : sourceFiles) {
|
||||
println(" " + p.toString());
|
||||
try (FileChannel sourceChannel = FileChannel.open(p)) {
|
||||
long rem = Files.size(p);
|
||||
while (rem > 0) {
|
||||
long n = Math.min(rem, 1024 * 1024);
|
||||
long w = out.transferFrom(sourceChannel, pos, n);
|
||||
pos += w;
|
||||
rem -= w;
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
throw new IllegalStateException("Could not copy recording chunk " + p + " to new file. " + ioe.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,195 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2018, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.cmd;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Deque;
|
||||
import java.util.List;
|
||||
|
||||
import jdk.jfr.internal.consumer.ChunkHeader;
|
||||
import jdk.jfr.internal.consumer.RecordingInput;
|
||||
|
||||
final class SplitCommand extends Command {
|
||||
|
||||
@Override
|
||||
public String getOptionSyntax() {
|
||||
return "[--maxchunks <chunks>] <file>";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayOptionUsage() {
|
||||
println(" --maxchunks <chunks> Maximum number of chunks per splitted file (default 5).");
|
||||
println(" The chunk size varies, but is typically around 15 MB.");
|
||||
println();
|
||||
println(" <file> Location of recording file (.jfr) to split");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "split";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Splits a recording file into smaller files";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Deque<String> options) {
|
||||
if (options.isEmpty()) {
|
||||
userFailed("Missing file");
|
||||
}
|
||||
ensureMaxArgumentCount(options, 3);
|
||||
Path file = Paths.get(options.removeLast());
|
||||
ensureFileExist(file);
|
||||
ensureJFRFile(file);
|
||||
int maxchunks = 5;
|
||||
if (!options.isEmpty()) {
|
||||
String option = options.pop();
|
||||
if (!"--maxchunks".equals(option)) {
|
||||
userFailed("Unknown option " + option);
|
||||
}
|
||||
if (options.isEmpty()) {
|
||||
userFailed("Missing value for --maxChunks");
|
||||
}
|
||||
String value = options.pop();
|
||||
try {
|
||||
maxchunks = Integer.parseInt(value);
|
||||
if (maxchunks < 1) {
|
||||
userFailed("Must be at least one chunk per file.");
|
||||
}
|
||||
} catch (NumberFormatException nfe) {
|
||||
userFailed("Not a valid value for --maxchunks.");
|
||||
}
|
||||
}
|
||||
ensureMaxArgumentCount(options, 0);
|
||||
println();
|
||||
println("Examining recording " + file + " ...");
|
||||
List<Long> sizes;
|
||||
|
||||
try {
|
||||
sizes = findChunkSizes(file);
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException("Unexpected error. " + e.getMessage());
|
||||
}
|
||||
if (sizes.size() <= maxchunks) {
|
||||
throw new IllegalStateException("Number of chunks in recording (" + sizes.size() + ") doesn't exceed max chunks (" + maxchunks + ")");
|
||||
}
|
||||
println();
|
||||
|
||||
println();
|
||||
if (sizes.size() > 0) {
|
||||
print("File consists of " + sizes.size() + " chunks. The recording will be split into ");
|
||||
sizes = combineChunkSizes(sizes, maxchunks);
|
||||
println(sizes.size() + " files with at most " + maxchunks + " chunks per file.");
|
||||
println();
|
||||
|
||||
try {
|
||||
splitFile(file, sizes);
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException("Unexpected error. " + e.getMessage());
|
||||
}
|
||||
} else {
|
||||
println("No JFR chunks found in file. ");
|
||||
}
|
||||
}
|
||||
|
||||
private List<Long> findChunkSizes(Path p) throws IOException {
|
||||
try (RecordingInput input = new RecordingInput(p.toFile())) {
|
||||
List<Long> sizes = new ArrayList<>();
|
||||
ChunkHeader ch = new ChunkHeader(input);
|
||||
sizes.add(ch.getSize());
|
||||
while (!ch.isLastChunk()) {
|
||||
ch = ch.nextHeader();
|
||||
sizes.add(ch.getSize());
|
||||
}
|
||||
return sizes;
|
||||
}
|
||||
}
|
||||
|
||||
private List<Long> combineChunkSizes(List<Long> sizes, int chunksPerFile) {
|
||||
List<Long> reduced = new ArrayList<Long>();
|
||||
long size = sizes.get(0);
|
||||
for (int n = 1; n < sizes.size(); n++) {
|
||||
if (n % chunksPerFile == 0) {
|
||||
reduced.add(size);
|
||||
size = 0;
|
||||
}
|
||||
size += sizes.get(n);
|
||||
}
|
||||
reduced.add(size);
|
||||
return reduced;
|
||||
}
|
||||
|
||||
private void splitFile(Path file, List<Long> splitPositions) throws IOException {
|
||||
|
||||
int padAmountZeros = String.valueOf(splitPositions.size() - 1).length();
|
||||
String fileName = file.toString();
|
||||
String fileFormatter = fileName.subSequence(0, fileName.length() - 4) + "_%0" + padAmountZeros + "d.jfr";
|
||||
for (int i = 0; i < splitPositions.size(); i++) {
|
||||
Path p = Paths.get(String.format(fileFormatter, i));
|
||||
if (Files.exists(p)) {
|
||||
throw new IllegalStateException("Can't create split file " + p + ", a file with that name already exist");
|
||||
}
|
||||
}
|
||||
DataInputStream stream = new DataInputStream(new BufferedInputStream(new FileInputStream(file.toFile())));
|
||||
|
||||
for (int i = 0; i < splitPositions.size(); i++) {
|
||||
Long l = splitPositions.get(i);
|
||||
byte[] bytes = readBytes(stream, l.intValue());
|
||||
Path p = Paths.get(String.format(fileFormatter, i));
|
||||
File splittedFile = p.toFile();
|
||||
println("Writing " + splittedFile + " ...");
|
||||
FileOutputStream fos = new FileOutputStream(splittedFile);
|
||||
fos.write(bytes);
|
||||
fos.close();
|
||||
}
|
||||
stream.close();
|
||||
}
|
||||
|
||||
private byte[] readBytes(InputStream stream, int count) throws IOException {
|
||||
byte[] data = new byte[count];
|
||||
int totalRead = 0;
|
||||
while (totalRead < data.length) {
|
||||
int read = stream.read(data, totalRead, data.length - totalRead);
|
||||
if (read == -1) {
|
||||
throw new IOException("Unexpected end of data.");
|
||||
}
|
||||
totalRead += read;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@ -1,111 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2018, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.cmd;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
abstract class StructuredWriter {
|
||||
private final static String LINE_SEPARATOR = String.format("%n");
|
||||
|
||||
private final PrintWriter out;
|
||||
private final StringBuilder builder = new StringBuilder(4000);
|
||||
|
||||
private char[] indentionArray = new char[0];
|
||||
private int indent = 0;
|
||||
private int column;
|
||||
|
||||
StructuredWriter(PrintWriter p) {
|
||||
out = p;
|
||||
}
|
||||
|
||||
final protected int getColumn() {
|
||||
return column;
|
||||
}
|
||||
|
||||
// Flush to print writer
|
||||
public final void flush() {
|
||||
out.print(builder.toString());
|
||||
builder.setLength(0);
|
||||
}
|
||||
|
||||
final public void printIndent() {
|
||||
builder.append(indentionArray, 0, indent);
|
||||
column += indent;
|
||||
}
|
||||
|
||||
final public void println() {
|
||||
builder.append(LINE_SEPARATOR);
|
||||
column = 0;
|
||||
}
|
||||
|
||||
final public void print(String... texts) {
|
||||
for (String text : texts) {
|
||||
print(text);
|
||||
}
|
||||
}
|
||||
|
||||
final public void printAsString(Object o) {
|
||||
print(String.valueOf(o));
|
||||
}
|
||||
|
||||
final public void print(String text) {
|
||||
builder.append(text);
|
||||
column += text.length();
|
||||
}
|
||||
|
||||
final public void print(char c) {
|
||||
builder.append(c);
|
||||
column++;
|
||||
}
|
||||
|
||||
final public void print(int value) {
|
||||
print(String.valueOf(value));
|
||||
}
|
||||
|
||||
final public void indent() {
|
||||
indent += 2;
|
||||
updateIndent();
|
||||
}
|
||||
|
||||
final public void retract() {
|
||||
indent -= 2;
|
||||
updateIndent();
|
||||
}
|
||||
|
||||
final public void println(String text) {
|
||||
print(text);
|
||||
println();
|
||||
}
|
||||
|
||||
private void updateIndent() {
|
||||
if (indent > indentionArray.length) {
|
||||
indentionArray = new char[indent];
|
||||
for (int i = 0; i < indentionArray.length; i++) {
|
||||
indentionArray[i] = ' ';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,173 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2018, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.cmd;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Deque;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import jdk.jfr.EventType;
|
||||
import jdk.jfr.internal.MetadataDescriptor;
|
||||
import jdk.jfr.internal.Type;
|
||||
import jdk.jfr.internal.consumer.ChunkHeader;
|
||||
import jdk.jfr.internal.consumer.RecordingInput;
|
||||
|
||||
final class SummaryCommand extends Command {
|
||||
|
||||
private static class Statistics {
|
||||
Statistics(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
String name;
|
||||
long count;
|
||||
long size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOptionSyntax() {
|
||||
return "<file>";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayOptionUsage() {
|
||||
println(" <file> Location of the recording file (.jfr) to display information about");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "summary";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Display general information about a recording file (.jfr)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Deque<String> options) {
|
||||
if (options.isEmpty()) {
|
||||
userFailed("Missing file");
|
||||
}
|
||||
ensureMaxArgumentCount(options, 1);
|
||||
Path p = Paths.get(options.remove());
|
||||
ensureFileExist(p);
|
||||
ensureJFRFile(p);
|
||||
try {
|
||||
printInformation(p);
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException("Unexpected error. " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void printInformation(Path p) throws IOException {
|
||||
long totalSize = 0;
|
||||
long totalDuration = 0;
|
||||
long chunks = 0;
|
||||
|
||||
try (RecordingInput input = new RecordingInput(p.toFile())) {
|
||||
ChunkHeader first = new ChunkHeader(input);
|
||||
ChunkHeader ch = first;
|
||||
String eventPrefix = Type.EVENT_NAME_PREFIX;
|
||||
if (first.getMajor() == 1) {
|
||||
eventPrefix = "com.oracle.jdk.";
|
||||
}
|
||||
HashMap<Long, Statistics> stats = new HashMap<>();
|
||||
stats.put(0L, new Statistics(eventPrefix + "Metadata"));
|
||||
stats.put(1L, new Statistics(eventPrefix + "CheckPoint"));
|
||||
int minWidth = 0;
|
||||
while (true) {
|
||||
long chunkEnd = ch.getEnd();
|
||||
MetadataDescriptor md = ch.readMetadata();
|
||||
|
||||
for (EventType eventType : md.getEventTypes()) {
|
||||
stats.computeIfAbsent(eventType.getId(), (e) -> new Statistics(eventType.getName()));
|
||||
minWidth = Math.max(minWidth, eventType.getName().length());
|
||||
}
|
||||
|
||||
totalSize += ch.getSize();
|
||||
totalDuration += ch.getDuration();
|
||||
chunks++;
|
||||
input.position(ch.getEventStart());
|
||||
while (input.position() < chunkEnd) {
|
||||
|
||||
long pos = input.position();
|
||||
int size = input.readInt();
|
||||
long eventTypeId = input.readLong();
|
||||
Statistics s = stats.get(eventTypeId);
|
||||
|
||||
if (s != null) {
|
||||
s.count++;
|
||||
s.size += size;
|
||||
}
|
||||
input.position(pos + size);
|
||||
}
|
||||
if (ch.isLastChunk()) {
|
||||
break;
|
||||
}
|
||||
ch = ch.nextHeader();
|
||||
}
|
||||
println();
|
||||
long epochSeconds = first.getStartNanos() / 1_000_000_000L;
|
||||
long adjustNanos = first.getStartNanos() - epochSeconds * 1_000_000_000L;
|
||||
println(" Version: " + first.getMajor() + "." + first.getMinor());
|
||||
println(" Chunks: " + chunks);
|
||||
println(" Size: " + totalSize + " bytes");
|
||||
println(" Start: " + Instant.ofEpochSecond(epochSeconds, adjustNanos));
|
||||
println(" Duration: " + Duration.ofNanos(totalDuration));
|
||||
println();
|
||||
println(" Start Ticks: " + first.getStartTicks());
|
||||
println(" Ticks / Second: " + first.getTicksPerSecond());
|
||||
|
||||
List<Statistics> statsList = new ArrayList<>(stats.values());
|
||||
Collections.sort(statsList, (u, v) -> Long.compare(v.count, u.count));
|
||||
println();
|
||||
String header = " Count Size (bytes) ";
|
||||
String typeHeader = " Event Type";
|
||||
minWidth = Math.max(minWidth, typeHeader.length());
|
||||
println(typeHeader + pad(minWidth - typeHeader.length(), ' ') + header);
|
||||
println(pad(minWidth + header.length(), '='));
|
||||
for (Statistics s : statsList) {
|
||||
System.out.printf(" %-" + minWidth + "s%10d %12d\n", s.name, s.count, s.size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String pad(int count, char c) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < count; i++) {
|
||||
sb.append(c);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@ -1,191 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2018, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.cmd;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import jdk.jfr.EventType;
|
||||
import jdk.jfr.ValueDescriptor;
|
||||
import jdk.jfr.consumer.RecordedEvent;
|
||||
import jdk.jfr.consumer.RecordedObject;
|
||||
import jdk.jfr.consumer.RecordingFile;
|
||||
|
||||
final class XMLWriter extends StructuredWriter {
|
||||
|
||||
public XMLWriter(PrintWriter destination) {
|
||||
super(destination);
|
||||
}
|
||||
|
||||
public void print(Path source) throws IOException {
|
||||
try (RecordingFile es = new RecordingFile(source)) {
|
||||
println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
||||
println("<recording>");
|
||||
indent();
|
||||
printIndent();
|
||||
println("<events>");
|
||||
indent();
|
||||
while (es.hasMoreEvents()) {
|
||||
printEvent(es.readEvent());
|
||||
flush();
|
||||
}
|
||||
retract();
|
||||
printIndent();
|
||||
println("</events>");
|
||||
retract();
|
||||
println("</recording>");
|
||||
flush();
|
||||
}
|
||||
}
|
||||
|
||||
private void printEvent(RecordedEvent e) throws IOException {
|
||||
EventType type = e.getEventType();
|
||||
printIndent();
|
||||
print("<event");
|
||||
printAttribute("typeId", String.valueOf(type.getId()));
|
||||
printAttribute("name", type.getName());
|
||||
printAttribute("startTime",e.getStartTime().toString());
|
||||
printAttribute("duration", e.getDuration().toString());
|
||||
print(">");
|
||||
printObject(e);
|
||||
printIndent();
|
||||
println("</event>");
|
||||
println();
|
||||
}
|
||||
|
||||
private void printAttribute(String name, String value) {
|
||||
print(" ", name, "=\"", value, "\"");
|
||||
}
|
||||
|
||||
public void printObject(RecordedObject struct) {
|
||||
println();
|
||||
indent();
|
||||
for (ValueDescriptor v : struct.getFields()) {
|
||||
printValueDescriptor(v, struct.getValue(v.getName()), -1);
|
||||
}
|
||||
retract();
|
||||
}
|
||||
|
||||
private void printArray(ValueDescriptor v, Object[] array) {
|
||||
println();
|
||||
indent();
|
||||
for (int index = 0; index < array.length; index++) {
|
||||
printValueDescriptor(v, array[index], index);
|
||||
}
|
||||
retract();
|
||||
}
|
||||
|
||||
private void printValueDescriptor(ValueDescriptor vd, Object value, int index) {
|
||||
boolean arrayElement = index != -1;
|
||||
String name = arrayElement ? null : vd.getName();
|
||||
if (vd.isArray() && !arrayElement) {
|
||||
if (printBeginElement("array", name, value, index)) {
|
||||
printArray(vd, (Object[]) value);
|
||||
printIndent();
|
||||
printEndElement("array");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!vd.getFields().isEmpty()) {
|
||||
if (printBeginElement("struct", name, value, index)) {
|
||||
printObject((RecordedObject) value);
|
||||
printIndent();
|
||||
printEndElement("struct");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (printBeginElement("value", name, value, index)) {
|
||||
printEscaped(String.valueOf(value));
|
||||
printEndElement("value");
|
||||
}
|
||||
}
|
||||
|
||||
private boolean printBeginElement(String elementName, String name, Object value, int index) {
|
||||
printIndent();
|
||||
print("<", elementName);
|
||||
if (name != null) {
|
||||
printAttribute("name", name);
|
||||
}
|
||||
if (index != -1) {
|
||||
printAttribute("index", Integer.toString(index));
|
||||
}
|
||||
if (value == null) {
|
||||
print("><null/></");
|
||||
print(elementName);
|
||||
println(">");
|
||||
return false;
|
||||
}
|
||||
if (value.getClass().isArray()) {
|
||||
Object[] array = (Object[]) value;
|
||||
printAttribute("size", Integer.toString(array.length));
|
||||
}
|
||||
print(">");
|
||||
return true;
|
||||
}
|
||||
|
||||
private void printEndElement(String elementName) {
|
||||
print("</");
|
||||
print(elementName);
|
||||
println(">");
|
||||
}
|
||||
|
||||
private void printEscaped(String text) {
|
||||
for (int i = 0; i < text.length(); i++) {
|
||||
printEscaped(text.charAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
private void printEscaped(char c) {
|
||||
if (c == 34) {
|
||||
print(""");
|
||||
return;
|
||||
}
|
||||
if (c == 38) {
|
||||
print("&");
|
||||
return;
|
||||
}
|
||||
if (c == 39) {
|
||||
print("'");
|
||||
return;
|
||||
}
|
||||
if (c == 60) {
|
||||
print("<");
|
||||
return;
|
||||
}
|
||||
if (c == 62) {
|
||||
print(">");
|
||||
return;
|
||||
}
|
||||
if (c > 0x7F) {
|
||||
print("&#");
|
||||
print((int) c);
|
||||
print(';');
|
||||
return;
|
||||
}
|
||||
print(c);
|
||||
}
|
||||
}
|
||||
@ -1,140 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2018, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.cmd;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import jdk.jfr.Configuration;
|
||||
import jdk.jfr.Event;
|
||||
import jdk.jfr.Recording;
|
||||
import jdk.test.lib.Utils;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.process.ProcessTools;;
|
||||
|
||||
final class ExecuteHelper {
|
||||
|
||||
public static Object[] array;
|
||||
|
||||
static class CustomEvent extends Event {
|
||||
int intValue;
|
||||
long longValue;
|
||||
double doubliValue;
|
||||
float floatValue;
|
||||
String stringValue;
|
||||
Short shortValue;
|
||||
boolean booleanValue;
|
||||
char charValue;
|
||||
double trickyDouble;
|
||||
}
|
||||
|
||||
public static OutputAnalyzer run(String... args) {
|
||||
String[] array = new String[args.length + 1];
|
||||
System.arraycopy(args, 0, array, 1, args.length);
|
||||
array[0] = "jdk.jfr.internal.cmd.Execute";
|
||||
try {
|
||||
return ProcessTools.executeTestJava(array);
|
||||
} catch (Exception e) {
|
||||
String message = String.format("Caught exception while executing '%s'", Arrays.asList(array));
|
||||
throw new RuntimeException(message, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void emitCustomEvents() {
|
||||
// Custom events with potentially tricky values
|
||||
CustomEvent event1 = new CustomEvent();
|
||||
event1.trickyDouble = Double.NaN;
|
||||
event1.intValue = Integer.MIN_VALUE;
|
||||
event1.longValue = Long.MIN_VALUE;
|
||||
event1.doubliValue = Double.MIN_VALUE;
|
||||
event1.floatValue = Float.MIN_VALUE;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < 512; i++) {
|
||||
sb.append((char) i);
|
||||
}
|
||||
sb.append("\u2324");
|
||||
event1.stringValue = sb.toString();
|
||||
event1.shortValue = Short.MIN_VALUE;
|
||||
event1.booleanValue = true;
|
||||
event1.booleanValue = false;
|
||||
event1.charValue = '\b';
|
||||
event1.commit();
|
||||
|
||||
CustomEvent event2 = new CustomEvent();
|
||||
event2.trickyDouble = Double.NEGATIVE_INFINITY;
|
||||
event2.intValue = Integer.MAX_VALUE;
|
||||
event2.longValue = Long.MAX_VALUE;
|
||||
event2.doubliValue = Double.MAX_VALUE;
|
||||
event2.floatValue = Float.MAX_VALUE;
|
||||
event2.stringValue = null;
|
||||
event2.shortValue = Short.MAX_VALUE;
|
||||
event2.booleanValue = false;
|
||||
event2.charValue = 0;
|
||||
event2.commit();
|
||||
}
|
||||
|
||||
public static Path createProfilingRecording() throws Exception {
|
||||
Path file = Utils.createTempFile("profiling-recording", ".jfr");
|
||||
// Create a recording with some data
|
||||
try (Recording r = new Recording(Configuration.getConfiguration("profile"))) {
|
||||
r.start();
|
||||
|
||||
// Allocation event
|
||||
array = new Object[1000000];
|
||||
array = null;
|
||||
|
||||
// Class loading event etc
|
||||
provokeClassLoading();
|
||||
|
||||
// GC events
|
||||
System.gc();
|
||||
|
||||
// ExecutionSample
|
||||
long t = System.currentTimeMillis();
|
||||
while (System.currentTimeMillis() - t < 50) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
// Other periodic events, i.e CPU load
|
||||
Thread.sleep(1000);
|
||||
|
||||
r.stop();
|
||||
r.dump(file);
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
private static void provokeClassLoading() {
|
||||
// Matching a string with regexp
|
||||
// is expected to load some classes and generate some VM events
|
||||
Pattern p = Pattern.compile("a*b");
|
||||
Matcher m = p.matcher("aaaaab");
|
||||
m.matches();
|
||||
}
|
||||
}
|
||||
@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2018, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.cmd;
|
||||
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary Test help
|
||||
* @key jfr
|
||||
* @requires vm.hasJFR
|
||||
* @library /test/lib /test/jdk
|
||||
* @run main/othervm jdk.jfr.cmd.TestHelp
|
||||
*/
|
||||
public class TestHelp {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
OutputAnalyzer output = ExecuteHelper.run("help");
|
||||
output.shouldContain("Available commands are:");
|
||||
output.shouldContain("print");
|
||||
output.shouldContain("reconstruct");
|
||||
output.shouldContain("summary");
|
||||
output.shouldContain("help");
|
||||
|
||||
output = ExecuteHelper.run("help", "help");
|
||||
output.shouldContain("Available commands are:");
|
||||
|
||||
output = ExecuteHelper.run("help", "wrongcommand");
|
||||
output.shouldContain("Unknown command");
|
||||
|
||||
output = ExecuteHelper.run("help", "wrongcommand", "wrongarguments");
|
||||
output.shouldContain("Too many arguments");
|
||||
}
|
||||
}
|
||||
@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2018, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.cmd;
|
||||
|
||||
import java.io.FileWriter;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import jdk.test.lib.Utils;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary Test jfr print
|
||||
* @key jfr
|
||||
* @requires vm.hasJFR
|
||||
* @library /test/lib /test/jdk
|
||||
* @run main/othervm jdk.jfr.cmd.TestPrint
|
||||
*/
|
||||
public class TestPrint {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
OutputAnalyzer output = ExecuteHelper.run("print");
|
||||
output.shouldContain("Missing file");
|
||||
|
||||
output = ExecuteHelper.run("print", "missing.jfr");
|
||||
output.shouldContain("Could not find file ");
|
||||
|
||||
output = ExecuteHelper.run("print", "missing.jfr", "option1", "option2");
|
||||
output.shouldContain("Too many arguments");
|
||||
|
||||
Path file = Utils.createTempFile("faked-print-file", ".jfr");
|
||||
FileWriter fw = new FileWriter(file.toFile());
|
||||
fw.write('d');
|
||||
fw.close();
|
||||
output = ExecuteHelper.run("print", "--wrongOption", file.toAbsolutePath().toString());
|
||||
output.shouldContain("Unknown option");
|
||||
Files.delete(file);
|
||||
|
||||
// Also see TestPrintJSON, TestPrintXML and TestPrintDefault.
|
||||
}
|
||||
}
|
||||
@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2018, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.cmd;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @key jfr
|
||||
* @summary Tests print --json
|
||||
* @requires vm.hasJFR
|
||||
*
|
||||
* @library /test/lib /test/jdk
|
||||
* @modules java.scripting
|
||||
* jdk.jfr
|
||||
*
|
||||
* @run main/othervm jdk.jfr.cmd.TestPrintDefault
|
||||
*/
|
||||
public class TestPrintDefault {
|
||||
|
||||
public static void main(String... args) throws Exception {
|
||||
|
||||
Path recordingFile = ExecuteHelper.createProfilingRecording().toAbsolutePath();
|
||||
|
||||
OutputAnalyzer output = ExecuteHelper.run("print", recordingFile.toString());
|
||||
output.shouldContain("JVMInformation");
|
||||
}
|
||||
}
|
||||
@ -1,149 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2018, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.cmd;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptEngineManager;
|
||||
|
||||
import jdk.jfr.ValueDescriptor;
|
||||
import jdk.jfr.consumer.RecordedEvent;
|
||||
import jdk.jfr.consumer.RecordedObject;
|
||||
import jdk.jfr.consumer.RecordingFile;
|
||||
import jdk.nashorn.api.scripting.JSObject;
|
||||
import jdk.test.lib.Asserts;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @key jfr
|
||||
* @summary Tests print --json
|
||||
* @requires vm.hasJFR
|
||||
*
|
||||
* @library /test/lib /test/jdk
|
||||
* @modules jdk.scripting.nashorn
|
||||
* jdk.jfr
|
||||
*
|
||||
* @run main/othervm jdk.jfr.cmd.TestPrintJSON
|
||||
*/
|
||||
public class TestPrintJSON {
|
||||
|
||||
public static void main(String... args) throws Exception {
|
||||
|
||||
Path recordingFile = ExecuteHelper.createProfilingRecording().toAbsolutePath();
|
||||
|
||||
OutputAnalyzer output = ExecuteHelper.run("print", "--json", recordingFile.toString());
|
||||
String json = output.getStdout();
|
||||
|
||||
// Parse JSON using Nashorn
|
||||
String statement = "var jsonObject = " + json;
|
||||
ScriptEngineManager factory = new ScriptEngineManager();
|
||||
ScriptEngine engine = factory.getEngineByName("nashorn");
|
||||
engine.eval(statement);
|
||||
JSObject o = (JSObject) engine.get("jsonObject");
|
||||
JSObject recording = (JSObject) o.getMember("recording");
|
||||
JSObject events = (JSObject) recording.getMember("events");
|
||||
|
||||
// Verify events are equal
|
||||
try (RecordingFile rf = new RecordingFile(recordingFile)) {
|
||||
for (Object jsonEvent : events.values()) {
|
||||
RecordedEvent recordedEvent = rf.readEvent();
|
||||
double typeId = recordedEvent.getEventType().getId();
|
||||
String startTime = recordedEvent.getStartTime().toString();
|
||||
String duration = recordedEvent.getDuration().toString();
|
||||
Asserts.assertEquals(typeId, ((Number) ((JSObject) jsonEvent).getMember("typeId")).doubleValue());
|
||||
Asserts.assertEquals(startTime, ((JSObject) jsonEvent).getMember("startTime"));
|
||||
Asserts.assertEquals(duration, ((JSObject) jsonEvent).getMember("duration"));
|
||||
assertEquals(jsonEvent, recordedEvent);
|
||||
}
|
||||
Asserts.assertFalse(rf.hasMoreEvents(), "Incorrect number of events");
|
||||
}
|
||||
}
|
||||
|
||||
private static void assertEquals(Object jsonObject, Object jfrObject) throws Exception {
|
||||
// Check object
|
||||
if (jfrObject instanceof RecordedObject) {
|
||||
JSObject values = (JSObject) ((JSObject) jsonObject).getMember("values");
|
||||
RecordedObject recObject = (RecordedObject) jfrObject;
|
||||
Asserts.assertEquals(values.values().size(), recObject.getFields().size());
|
||||
for (ValueDescriptor v : recObject.getFields()) {
|
||||
String name = v.getName();
|
||||
assertEquals(values.getMember(name), recObject.getValue(name));
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Check array
|
||||
if (jfrObject != null && jfrObject.getClass().isArray()) {
|
||||
Object[] jfrArray = (Object[]) jfrObject;
|
||||
JSObject jsArray = (JSObject) jsonObject;
|
||||
for (int i = 0; i < jfrArray.length; i++) {
|
||||
assertEquals(jsArray.getSlot(i), jfrArray[i]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
String jsonText = String.valueOf(jsonObject);
|
||||
// Double.NaN / Double.Inifinity is not supported by JSON format,
|
||||
// use null
|
||||
if (jfrObject instanceof Double) {
|
||||
double expected = ((Double) jfrObject);
|
||||
if (Double.isInfinite(expected) || Double.isNaN(expected)) {
|
||||
Asserts.assertEquals("null", jsonText);
|
||||
return;
|
||||
}
|
||||
double value = Double.parseDouble(jsonText);
|
||||
Asserts.assertEquals(expected, value);
|
||||
return;
|
||||
}
|
||||
// Float.NaN / Float.Inifinity is not supported by JSON format,
|
||||
// use null
|
||||
if (jfrObject instanceof Float) {
|
||||
float expected = ((Float) jfrObject);
|
||||
if (Float.isInfinite(expected) || Float.isNaN(expected)) {
|
||||
Asserts.assertEquals("null", jsonText);
|
||||
return;
|
||||
}
|
||||
float value = Float.parseFloat(jsonText);
|
||||
Asserts.assertEquals(expected, value);
|
||||
return;
|
||||
}
|
||||
if (jfrObject instanceof Integer) {
|
||||
Integer expected = ((Integer) jfrObject);
|
||||
double value = Double.parseDouble(jsonText);
|
||||
Asserts.assertEquals(expected.doubleValue(), value);
|
||||
return;
|
||||
}
|
||||
if (jfrObject instanceof Long) {
|
||||
Long expected = ((Long) jfrObject);
|
||||
double value = Double.parseDouble(jsonText);
|
||||
Asserts.assertEquals(expected.doubleValue(), value);
|
||||
return;
|
||||
}
|
||||
|
||||
String jfrText = String.valueOf(jfrObject);
|
||||
Asserts.assertEquals(jfrText, jsonText, "Primitive values don't match. JSON = " + jsonText);
|
||||
}
|
||||
}
|
||||
@ -1,222 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2018, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.cmd;
|
||||
|
||||
import java.io.StringReader;
|
||||
import java.nio.file.Path;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.AbstractMap.SimpleEntry;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Stack;
|
||||
|
||||
import javax.xml.parsers.SAXParser;
|
||||
import javax.xml.parsers.SAXParserFactory;
|
||||
|
||||
import jdk.jfr.ValueDescriptor;
|
||||
import jdk.jfr.consumer.RecordedEvent;
|
||||
import jdk.jfr.consumer.RecordedObject;
|
||||
import jdk.jfr.consumer.RecordingFile;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.helpers.DefaultHandler;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @key jfr
|
||||
* @summary Tests print --xml
|
||||
* @requires vm.hasJFR
|
||||
*
|
||||
* @library /test/lib /test/jdk
|
||||
* @modules java.scripting
|
||||
* java.xml
|
||||
* jdk.jfr
|
||||
*
|
||||
* @run main/othervm jdk.jfr.cmd.TestPrintXML
|
||||
*/
|
||||
public class TestPrintXML {
|
||||
|
||||
public static void main(String... args) throws Exception {
|
||||
|
||||
Path recordingFile = ExecuteHelper.createProfilingRecording().toAbsolutePath();
|
||||
|
||||
OutputAnalyzer output = ExecuteHelper.run("print", "--xml", recordingFile.toString());
|
||||
String xml = output.getStdout();
|
||||
System.out.println(xml);
|
||||
// Parse XML string
|
||||
SAXParserFactory factory = SAXParserFactory.newInstance();
|
||||
SAXParser sp = factory.newSAXParser();
|
||||
XMLReader xr = sp.getXMLReader();
|
||||
RecordingHandler handler = new RecordingHandler();
|
||||
xr.setContentHandler(handler);
|
||||
xr.parse(new InputSource(new StringReader(xml)));
|
||||
|
||||
// Verify that all data was written correctly
|
||||
Iterator<RecordedEvent> it = RecordingFile.readAllEvents(recordingFile).iterator();
|
||||
for (XMLEvent xmlEvent : handler.events) {
|
||||
RecordedEvent re = it.next();
|
||||
if (!compare(re, xmlEvent.values)) {
|
||||
System.out.println(re);
|
||||
System.out.println(xmlEvent.values.toString());
|
||||
throw new Exception("Event doesn't match");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static boolean compare(Object eventObject, Object xmlObject) {
|
||||
if (eventObject == null) {
|
||||
return xmlObject == null;
|
||||
}
|
||||
if (eventObject instanceof RecordedObject) {
|
||||
RecordedObject re = (RecordedObject) eventObject;
|
||||
Map<String, Object> xmlMap = (Map<String, Object>) xmlObject;
|
||||
List<ValueDescriptor> fields = re.getFields();
|
||||
if (fields.size() != xmlMap.size()) {
|
||||
return false;
|
||||
}
|
||||
for (ValueDescriptor v : fields) {
|
||||
String name = v.getName();
|
||||
if (!compare(re.getValue(name), xmlMap.get(name))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (eventObject.getClass().isArray()) {
|
||||
Object[] array = (Object[]) eventObject;
|
||||
Object[] xmlArray = (Object[]) xmlObject;
|
||||
if (array.length != xmlArray.length) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
if (!compare(array[i], xmlArray[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
String s1 = String.valueOf(eventObject);
|
||||
String s2 = (String) xmlObject;
|
||||
return s1.equals(s2);
|
||||
}
|
||||
|
||||
static class XMLEvent {
|
||||
String name;
|
||||
Instant startTime;
|
||||
Duration duration;
|
||||
Map<String, Object> values = new HashMap<>();
|
||||
|
||||
XMLEvent(String name, Instant startTime, Duration duration) {
|
||||
this.name = name;
|
||||
this.startTime = startTime;
|
||||
this.duration = duration;
|
||||
}
|
||||
}
|
||||
|
||||
public static final class RecordingHandler extends DefaultHandler {
|
||||
|
||||
private Stack<Object> objects = new Stack<>();
|
||||
private Stack<SimpleEntry<String, String>> elements = new Stack<>();
|
||||
private List<XMLEvent> events = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException {
|
||||
elements.push(new SimpleEntry<>(attrs.getValue("name"), attrs.getValue("index")));
|
||||
switch (qName) {
|
||||
case "null":
|
||||
objects.pop();
|
||||
objects.push(null);
|
||||
break;
|
||||
case "event":
|
||||
Instant startTime = Instant.parse(attrs.getValue("startTime"));
|
||||
Duration duration = Duration.parse(attrs.getValue("duration"));
|
||||
objects.push(new XMLEvent(attrs.getValue("name"), startTime, duration));
|
||||
break;
|
||||
case "struct":
|
||||
objects.push(new HashMap<String, Object>());
|
||||
break;
|
||||
case "array":
|
||||
objects.push(new Object[Integer.parseInt(attrs.getValue("size"))]);
|
||||
break;
|
||||
case "value":
|
||||
objects.push(new StringBuilder());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void characters(char[] ch, int start, int length) throws SAXException {
|
||||
if (!objects.isEmpty()) {
|
||||
Object o = objects.peek();
|
||||
if (o instanceof StringBuilder) {
|
||||
((StringBuilder) o).append(ch, start, length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void endElement(String uri, String localName, String qName) {
|
||||
SimpleEntry<String, String> element = elements.pop();
|
||||
switch (qName) {
|
||||
case "event":
|
||||
case "struct":
|
||||
case "array":
|
||||
case "value":
|
||||
String name = element.getKey();
|
||||
Object value = objects.pop();
|
||||
if (objects.isEmpty()) {
|
||||
events.add((XMLEvent) value);
|
||||
return;
|
||||
}
|
||||
if (value instanceof StringBuilder) {
|
||||
value = ((StringBuilder) value).toString();
|
||||
}
|
||||
Object parent = objects.peek();
|
||||
if (parent instanceof XMLEvent) {
|
||||
((XMLEvent) parent).values.put(name, value);
|
||||
}
|
||||
if (parent instanceof Map) {
|
||||
((Map<String, Object>) parent).put(name, value);
|
||||
}
|
||||
if (parent != null && parent.getClass().isArray()) {
|
||||
int index = Integer.parseInt(element.getValue());
|
||||
((Object[]) parent)[index] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,146 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2018, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.cmd;
|
||||
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import jdk.jfr.Event;
|
||||
import jdk.jfr.Name;
|
||||
import jdk.jfr.Recording;
|
||||
import jdk.jfr.consumer.RecordedEvent;
|
||||
import jdk.jfr.consumer.RecordingFile;
|
||||
import jdk.jfr.internal.Repository;
|
||||
import jdk.jfr.internal.SecuritySupport.SafePath;
|
||||
import jdk.test.lib.Asserts;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary Test jfr reconstruct
|
||||
* @key jfr
|
||||
* @requires vm.hasJFR
|
||||
* @library /test/lib /test/jdk
|
||||
* @modules jdk.jfr/jdk.jfr.internal
|
||||
* @run main/othervm jdk.jfr.cmd.TestReconstruct
|
||||
*/
|
||||
public class TestReconstruct {
|
||||
|
||||
@Name("Correlation")
|
||||
static class CorrelationEvent extends Event {
|
||||
int id;
|
||||
}
|
||||
private static int RECORDING_COUNT = 5;
|
||||
|
||||
@SuppressWarnings("resource")
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Create some disk recordings
|
||||
Recording[] recordings = new Recording[5];
|
||||
for (int i = 0; i < RECORDING_COUNT; i++) {
|
||||
Recording r = new Recording();
|
||||
r.setToDisk(true);
|
||||
r.start();
|
||||
CorrelationEvent ce = new CorrelationEvent();
|
||||
ce.id = i;
|
||||
ce.commit();
|
||||
r.stop();
|
||||
recordings[i] = r;
|
||||
}
|
||||
Path dir = Paths.get("reconstruction-parts");
|
||||
Files.createDirectories(dir);
|
||||
|
||||
long expectedCount = 0;
|
||||
for (int i = 0; i < RECORDING_COUNT; i++) {
|
||||
Path tmp = dir.resolve("chunk-part-" + i + ".jfr");
|
||||
recordings[i].dump(tmp);
|
||||
expectedCount += countEventInRecording(tmp);
|
||||
}
|
||||
|
||||
SafePath repository = Repository.getRepository().getRepositoryPath();
|
||||
Path destinationPath = Paths.get("reconstructed.jfr");
|
||||
|
||||
String directory = repository.toString();
|
||||
String destination = destinationPath.toAbsolutePath().toString();
|
||||
|
||||
// Test failure
|
||||
OutputAnalyzer output = ExecuteHelper.run("reconstruct");
|
||||
|
||||
output.shouldContain("Too few arguments");
|
||||
|
||||
output = ExecuteHelper.run("reconstruct", directory);
|
||||
output.shouldContain("Too few arguments");
|
||||
|
||||
output = ExecuteHelper.run("reconstruct", "not-a-directory", destination);
|
||||
output.shouldContain("Could not find disk repository at");
|
||||
|
||||
output = ExecuteHelper.run("reconstruct", directory, "not-a-destination");
|
||||
output.shouldContain("Filename must end with .jfr");
|
||||
|
||||
output = ExecuteHelper.run("reconstruct", "--wrongOption", directory, destination);
|
||||
output.shouldContain("Too many arguments");
|
||||
|
||||
FileWriter fw = new FileWriter(destination);
|
||||
fw.write('d');
|
||||
fw.close();
|
||||
output = ExecuteHelper.run("reconstruct", directory, destination);
|
||||
output.shouldContain("already exists");
|
||||
Files.delete(destinationPath);
|
||||
|
||||
// test success
|
||||
output = ExecuteHelper.run("reconstruct", directory, destination);
|
||||
System.out.println(output.getOutput());
|
||||
output.shouldContain("Reconstruction complete");
|
||||
|
||||
long reconstructedCount = countEventInRecording(destinationPath);
|
||||
Asserts.assertEquals(expectedCount, reconstructedCount);
|
||||
// Cleanup
|
||||
for (int i = 0; i < RECORDING_COUNT; i++) {
|
||||
recordings[i].close();
|
||||
}
|
||||
}
|
||||
|
||||
private static long countEventInRecording(Path file) throws IOException {
|
||||
Integer lastId = -1;
|
||||
try (RecordingFile rf = new RecordingFile(file)) {
|
||||
long count = 0;
|
||||
while (rf.hasMoreEvents()) {
|
||||
RecordedEvent re = rf.readEvent();
|
||||
if (re.getEventType().getName().equals("Correlation")) {
|
||||
Integer id = re.getValue("id");
|
||||
if (id < lastId) {
|
||||
Asserts.fail("Expected chunk number to increase");
|
||||
}
|
||||
lastId = id;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,121 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2018, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.cmd;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
import jdk.jfr.Configuration;
|
||||
import jdk.jfr.Recording;
|
||||
import jdk.jfr.consumer.RecordingFile;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary Test jfr split
|
||||
* @key jfr
|
||||
* @requires vm.hasJFR
|
||||
* @library /test/lib /test/jdk
|
||||
* @run main/othervm jdk.jfr.cmd.TestSplit
|
||||
*/
|
||||
public class TestSplit {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
SimpleDateFormat formatter = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss");
|
||||
String dateText = formatter.format(new Date());
|
||||
|
||||
Path recordingFileA = Paths.get("many-chunks-A-" + dateText + ".jfr");
|
||||
Path recordingFileB = Paths.get("many-chunks-B-" + dateText + ".jfr");
|
||||
makeRecordingWithChunks(6, recordingFileA);
|
||||
Files.copy(recordingFileA, recordingFileB);
|
||||
|
||||
String fileAText = recordingFileA.toAbsolutePath().toString();
|
||||
String fileBText = recordingFileB.toAbsolutePath().toString();
|
||||
|
||||
OutputAnalyzer output = ExecuteHelper.run("split");
|
||||
output.shouldContain("Missing file");
|
||||
|
||||
output = ExecuteHelper.run("split", "--wrongOption1", "..wrongOption2", "..wrongOption3", fileAText);
|
||||
output.shouldContain("Too many arguments");
|
||||
|
||||
output = ExecuteHelper.run("split", "--wrongOption", fileAText);
|
||||
output.shouldContain("Unknown option");
|
||||
|
||||
output = ExecuteHelper.run("split", "--wrongOption", "1", fileAText);
|
||||
output.shouldContain("Unknown option");
|
||||
|
||||
output = ExecuteHelper.run("split", "--maxchunks", "-3", fileAText);
|
||||
output.shouldContain("Must be at least one chunk per file");
|
||||
|
||||
output = ExecuteHelper.run("split", "--maxchunks", "1000", fileAText);
|
||||
output.shouldContain("Number of chunks in recording");
|
||||
output.shouldContain("doesn't exceed max chunks");
|
||||
output = ExecuteHelper.run("split", fileAText); // maxchunks is 5 by
|
||||
// default
|
||||
System.out.println(output.getOutput());
|
||||
System.out.println(fileAText);
|
||||
verifyRecording(fileAText.substring(0, fileAText.length() - 4) + "_1.jfr");
|
||||
verifyRecording(fileAText.substring(0, fileAText.length() - 4) + "_2.jfr");
|
||||
|
||||
output = ExecuteHelper.run("split", "--maxchunks", "2", fileBText);
|
||||
|
||||
verifyRecording(fileBText.substring(0, fileBText.length() - 4) + "_1.jfr");
|
||||
verifyRecording(fileBText.substring(0, fileBText.length() - 4) + "_2.jfr");
|
||||
verifyRecording(fileBText.substring(0, fileBText.length() - 4) + "_3.jfr");
|
||||
|
||||
output = ExecuteHelper.run("split", "--maxchunks", "2", fileBText);
|
||||
output.shouldContain("file with that name already exist");
|
||||
}
|
||||
|
||||
private static void verifyRecording(String name) throws IOException {
|
||||
System.out.println("split name " + name);
|
||||
try (RecordingFile rf = new RecordingFile(Paths.get(name))) {
|
||||
rf.readEvent();
|
||||
}
|
||||
}
|
||||
|
||||
// Will create at least 2 * count + 1 chunks.
|
||||
private static void makeRecordingWithChunks(int count, Path file) throws IOException, ParseException {
|
||||
Recording main = new Recording(Configuration.getConfiguration("default"));
|
||||
main.setToDisk(true);
|
||||
main.start();
|
||||
for (int i = 0; i < count; i++) {
|
||||
Recording r = new Recording();
|
||||
r.setToDisk(true);
|
||||
r.start();
|
||||
r.stop();
|
||||
r.close();
|
||||
}
|
||||
main.stop();
|
||||
main.dump(file);
|
||||
main.close();
|
||||
}
|
||||
}
|
||||
@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2018, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.cmd;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
import jdk.jfr.EventType;
|
||||
import jdk.jfr.consumer.RecordingFile;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary Test jfr info
|
||||
* @key jfr
|
||||
* @requires vm.hasJFR
|
||||
* @library /test/lib /test/jdk
|
||||
* @run main/othervm jdk.jfr.cmd.TestSummary
|
||||
*/
|
||||
public class TestSummary {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Path f = ExecuteHelper.createProfilingRecording().toAbsolutePath();
|
||||
String file = f.toAbsolutePath().toString();
|
||||
|
||||
OutputAnalyzer output = ExecuteHelper.run("summary");
|
||||
output.shouldContain("Missing file");
|
||||
|
||||
output = ExecuteHelper.run("summary", "--wrongOption", file);
|
||||
output.shouldContain("Too many arguments");
|
||||
|
||||
output = ExecuteHelper.run("summary", file);
|
||||
try (RecordingFile rf = new RecordingFile(f)) {
|
||||
for (EventType t : rf.readEventTypes()) {
|
||||
output.shouldContain(t.getName());
|
||||
}
|
||||
}
|
||||
output.shouldContain("Version");
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user