Skip to content

Commit

Permalink
Rework jstack to use java.base only
Browse files Browse the repository at this point in the history
In the target VM use only classes available in the java.base module.

Rework original implementation of jstack: "Implement jstack in 0.14" eclipse-openj9#5336

- Create the result string at the target instead of the attacher
- Delete unnecessary classes and packages
- Delete unit tests for deleted classes and other dead test code
- Minor stylistic cleanup while I have the files open

[ci skip]

Signed-off-by: Peter Bain <peter_bain@ca.ibm.com>
  • Loading branch information
pdbain-ibm committed Jun 21, 2019
1 parent eabc47d commit 25e124d
Show file tree
Hide file tree
Showing 23 changed files with 147 additions and 816 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
import java.util.ServiceLoader;
import openj9.tools.attach.diagnostics.base.DiagnosticProperties;
import openj9.tools.attach.diagnostics.base.DiagnosticUtils;
import openj9.tools.attach.diagnostics.spi.TargetDiagnosticsProvider;
/*[IF Sidecar19-SE]*/
import jdk.internal.vm.VMSupport;
/*[ELSE] Sidecar19-SE
Expand All @@ -64,7 +63,6 @@ final class Attachment extends Thread implements Response {
private String attachError;
private final AttachHandler handler;
private final String key;
private TargetDiagnosticsProvider diagProvider;
private static final String START_REMOTE_MANAGEMENT_AGENT = "startRemoteManagementAgent"; //$NON-NLS-1$
private static final String START_LOCAL_MANAGEMENT_AGENT = "startLocalManagementAgent"; //$NON-NLS-1$

Expand Down Expand Up @@ -131,7 +129,6 @@ private static final class MethodRefsHolder {
portNumber = rc.getPortNumber();
this.key = rc.getKey();
this.handler = attachHandler;
diagProvider = null;
setDaemon(true);
}

Expand Down Expand Up @@ -224,12 +221,6 @@ boolean doCommand(InputStream cmdStream, OutputStream respStream) {
AttachmentConnection.streamSend(respStream, Response.ERROR
+ " " + attachError); //$NON-NLS-1$
}
} else if (cmd.startsWith(Command.GET_THREAD_GROUP_INFO)) {
try {
replyWithProperties(getDiagnosticsProvider().getThreadGroupInfo());
} catch (Exception e) {
replyWithProperties(DiagnosticProperties.makeExceptionProperties(e));
}
} else if (cmd.startsWith(Command.GET_SYSTEM_PROPERTIES)) {
Properties internalProperties = com.ibm.oti.vm.VM.getVMLangAccess().internalGetProperties();
String argumentString = String.join(" ", com.ibm.oti.vm.VM.getVMArgs()); //$NON-NLS-1$
Expand Down Expand Up @@ -306,18 +297,6 @@ private void replyWithProperties(Properties props) throws IOException {
IPC.sendProperties(props, responseStream);
}

private TargetDiagnosticsProvider getDiagnosticsProvider() {
if (diagProvider == null) {
for (TargetDiagnosticsProvider p: ServiceLoader.load(TargetDiagnosticsProvider.class)) {
if (null != p) {
diagProvider = p;
break;
}
}
}
return diagProvider;
}

/**
* close socket and other cleanup
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ public interface Command {
static final String GET_AGENT_PROPERTIES = "ATTACH_GETAGENTPROPERTIES"; //$NON-NLS-1$
static final String START_MANAGEMENT_AGENT = "ATTACH_START_MANAGEMENT_AGENT"; //$NON-NLS-1$
static final String START_LOCAL_MANAGEMENT_AGENT = "ATTACH_START_LOCAL_MANAGEMENT_AGENT"; //$NON-NLS-1$
static final String GET_THREAD_GROUP_INFO = "ATTACH_GET_THREAD_INFO"; //$NON-NLS-1$
static final String ATTACH_DIAGNOSTICS_PREFIX = "ATTACH_DIAGNOSTICS:"; //$NON-NLS-1$

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
/*[INCLUDE-IF Sidecar16]*/
package com.ibm.tools.attach.target;

/*******************************************************************************
* Copyright (c) 2009, 2019 IBM Corp. and others
*
Expand All @@ -23,30 +21,32 @@
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
*******************************************************************************/

package com.ibm.tools.attach.target;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.security.SecureRandom;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Paths;
import java.nio.file.attribute.PosixFilePermission;
import java.security.SecureRandom;
import java.util.EnumSet;
import java.util.Set;
import java.util.Objects;
import java.util.Properties;
import java.util.Random;
import java.util.Set;

import static java.nio.file.attribute.PosixFilePermission.GROUP_READ;
import static java.nio.file.attribute.PosixFilePermission.GROUP_WRITE;
import static java.nio.file.attribute.PosixFilePermission.OTHERS_READ;
import static java.nio.file.attribute.PosixFilePermission.OTHERS_WRITE;
import static openj9.tools.attach.diagnostics.base.DiagnosticsInfo.OPENJ9_DIAGNOSTICS_PREFIX;
import static openj9.tools.attach.diagnostics.base.DiagnosticProperties.OPENJ9_DIAGNOSTICS_PREFIX;

/**
* Utility class for operating system calls
Expand Down Expand Up @@ -153,7 +153,7 @@ public static void checkOwnerAccessOnly(String filePath) throws IOException {
actualPermissions.retainAll(NON_OWNER_READ_WRITE);
if (!actualPermissions.isEmpty()) {
final String permissionString = Files.getPosixFilePermissions(Paths.get(filePath), LinkOption.NOFOLLOW_LINKS).toString();
logMessage("Wrong permissions: " +permissionString + " for ", filePath); //$NON-NLS-1$ //$NON-NLS-2$
logMessage("Wrong permissions: " + permissionString + " for ", filePath); //$NON-NLS-1$ //$NON-NLS-2$
/*[MSG "K0805", "{0} has permissions {1}, should have owner access only"]*/
throw new IOException(com.ibm.oti.util.Msg.getString("K0805", filePath, permissionString));//$NON-NLS-1$
}
Expand Down Expand Up @@ -308,8 +308,8 @@ static private native int createFileWithPermissionsImpl(String path,
static String getTmpDir() {
String tmpDir = getTempDirImpl();
if (null == tmpDir) {
IPC.logMessage("Could not get system temporary directory. Trying "+JAVA_IO_TMPDIR); //$NON-NLS-1$
tmpDir = com.ibm.oti.vm.VM.getVMLangAccess().internalGetProperties().getProperty(JAVA_IO_TMPDIR); //$NON-NLS-1$
logMessage("Could not get system temporary directory. Trying " + JAVA_IO_TMPDIR); //$NON-NLS-1$
tmpDir = com.ibm.oti.vm.VM.getVMLangAccess().internalGetProperties().getProperty(JAVA_IO_TMPDIR);
}
return tmpDir;
}
Expand Down Expand Up @@ -524,9 +524,9 @@ public static void sendProperties(Properties props, OutputStream outStream)
public static Properties receiveProperties(InputStream inStream, boolean requireNull)
throws IOException {
byte msgBuff[] = AttachmentConnection.streamReceiveBytes(inStream, 0, requireNull);
if (IPC.isLoggingEnabled()) {
if (isLoggingEnabled()) {
String propsString = new String(msgBuff, StandardCharsets.UTF_8);
IPC.logMessage("Received properties file:", propsString); //$NON-NLS-1$
logMessage("Received properties file:", propsString); //$NON-NLS-1$
}
Properties props = new Properties();
props.load(new ByteArrayInputStream(msgBuff));
Expand Down
2 changes: 0 additions & 2 deletions jcl/src/java.base/share/classes/module-info.java.extra
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,10 @@ exports com.ibm.oti.vm to java.management, jdk.attach, jdk.management, openj9.jv
exports com.ibm.oti.util to java.management, jdk.attach, jdk.jcmd, jdk.management, openj9.sharedclasses;
exports com.ibm.tools.attach.target to jdk.attach, jdk.jcmd, jdk.management;
exports openj9.management.internal to java.management;
exports openj9.tools.attach.diagnostics.spi to jdk.attach, jdk.jcmd;
exports openj9.tools.attach.diagnostics.base to jdk.attach, jdk.jcmd;
exports jdk.internal.org.objectweb.asm to openj9.dtfj, openj9.dtfjview;
// Following allows dtfj/dtfjview modules invoke module addReads & addExports programmatically via reflection APIs
exports jdk.internal.module to openj9.dtfj, openj9.dtfjview;
uses com.ibm.sharedclasses.spi.SharedClassProvider;
uses openj9.tools.attach.diagnostics.spi.TargetDiagnosticsProvider;
uses com.ibm.gpu.spi.GPUAssist.Provider;
exports com.ibm.gpu.spi to openj9.gpu;
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,15 @@
public class DiagnosticProperties {
private final Properties baseProperties;

/**
* Master prefix for property keys
*/
public static final String OPENJ9_DIAGNOSTICS_PREFIX = "openj9_diagnostics."; //$NON-NLS-1$
/**
* Use for commands which return a single string
*/
public static final String DIAGNOSTICS_STRING_RESULT = OPENJ9_DIAGNOSTICS_PREFIX + "string_result"; //$NON-NLS-1$

private static final String JAVA_LANG_STRING = "java.lang.String"; //$NON-NLS-1$

/**
Expand Down Expand Up @@ -249,7 +258,7 @@ public static void dumpPropertiesIfDebug(String msg, DiagnosticProperties props)
* @param props Properties object to dump
*/
public static void dumpPropertiesIfDebug(String msg, final Properties props) {
if (DiagnosticProperties.isDebug) {
if (isDebug) {
if (null != msg) {
System.err.println(msg);
}
Expand Down Expand Up @@ -294,7 +303,7 @@ public String printStringResult() {
buffWriter.println(msg);
}
} else {
buffWriter.println(getString(DiagnosticsInfo.DIAGNOSTICS_STRING_RESULT));
buffWriter.println(getString(DIAGNOSTICS_STRING_RESULT));
}
} catch (IOException e) {
buff = new StringWriter();
Expand All @@ -309,11 +318,11 @@ public String printStringResult() {
* Create a properties file to hold a single string.
*
* @param text text of the string
* @return properties file containing the string, plus success indication
* @return DiagnosticProperties object
*/
public static DiagnosticProperties makeStringResult(String text) {
DiagnosticProperties props = makeCommandSucceeded();
props.put(DiagnosticsInfo.DIAGNOSTICS_STRING_RESULT, text);
props.put(DIAGNOSTICS_STRING_RESULT, text);
return props;
}

Expand All @@ -327,12 +336,22 @@ public Properties toProperties() {
}

/**
* @return Properties file indicating success
* Report successful execution of a command
* @return DiagnosticProperties object
*/
public static DiagnosticProperties makeCommandSucceeded() {
return makeStatusProperties(false, null); // $NON-NLS-1$
}

/**
* Report an error in the command
* @param message error message
* @return DiagnosticProperties object
*/
public static DiagnosticProperties makeErrorProperties(String message) {
return makeStatusProperties(true, message); // $NON-NLS-1$
}

/**
* Encode information about an exception into properties.
*
Expand All @@ -355,7 +374,7 @@ public static Properties makeExceptionProperties(Exception e) {
*
* @param error true if the command failed
* @param msg status message
* @return properties file encoding the status and message
* @return DiagnosticProperties object
*/
public static DiagnosticProperties makeStatusProperties(boolean error, String msg) {
DiagnosticProperties props = new DiagnosticProperties();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,20 @@

package openj9.tools.attach.diagnostics.base;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Predicate;

import com.ibm.oti.vm.VM;
import com.ibm.tools.attach.target.IPC;

import openj9.management.internal.LockInfoBase;
import openj9.management.internal.ThreadInfoBase;

/**
* Common methods for the diagnostics tools
*
Expand All @@ -41,6 +47,11 @@ public class DiagnosticUtils {
* Command strings for executeDiagnosticCommand()
*/

/**
* Run Get the stack traces and other thread information.
*/
public static final String DIAGNOSTICS_THREAD_PRINT = "Thread.print"; //$NON-NLS-1$

/**
* Run System.gc();
*/
Expand All @@ -65,6 +76,7 @@ public class DiagnosticUtils {
* Report only live heap objects.
*/
public static final String LIVE_OPTION = "live"; //$NON-NLS-1$
private static final String THREAD_LOCKED_SYNCHRONIZERS_OPTION = "-l"; //$NON-NLS-1$

private static final Map<String, Function<String, DiagnosticProperties>> commandTable;

Expand All @@ -82,6 +94,19 @@ public static String makeHeapHistoCommand(boolean liveObjects) {
return cmd;
}

/**
* Create the command to run the Thread.print command
*
* @param lockedSynchronizers print the locked ownable synchronizers
* @return formatted string
*/
public static String makeThreadPrintCommand(boolean lockedSynchronizers) {
String cmd = lockedSynchronizers
? DIAGNOSTICS_THREAD_PRINT + DIAGNOSTICS_OPTION_SEPARATOR + THREAD_LOCKED_SYNCHRONIZERS_OPTION
: DIAGNOSTICS_THREAD_PRINT;
return cmd;
}

private static native String getHeapClassStatisticsImpl();

/**
Expand Down Expand Up @@ -120,6 +145,55 @@ private static DiagnosticProperties getHeapStatistics(String diagnosticCommand)
}
return DiagnosticProperties.makeStringResult(result);
}

private static DiagnosticProperties getThreadInfo(String diagnosticCommand) {
DiagnosticProperties result = null;
boolean okay = true;
boolean addSynchronizers = false;
String[] parts = diagnosticCommand.split(DIAGNOSTICS_OPTION_SEPARATOR);
/* only one option ("-l[=<BOOLEAN>]") is allowed, so the diagnosticCommand can comprise at most
* the base command and one option, with an optional value */
if (parts.length > 2) {
okay = false;
} else if (parts.length == 2) {
String option = parts[1];
if (option.startsWith(THREAD_LOCKED_SYNCHRONIZERS_OPTION)) {
if ((THREAD_LOCKED_SYNCHRONIZERS_OPTION.length() == option.length()) /* exact match */
|| option.toLowerCase().equals(THREAD_LOCKED_SYNCHRONIZERS_OPTION + "=true")) { //$NON-NLS-1$
addSynchronizers = true;
}
} else {
okay = false;
}
}
if (!okay) {
result = DiagnosticProperties.makeErrorProperties("Command not recognized: " + diagnosticCommand); //$NON-NLS-1$
} else {
StringWriter buffer = new StringWriter(2000);
PrintWriter bufferPrinter = new PrintWriter(buffer);
bufferPrinter.println(System.getProperty("java.vm.info")); //$NON-NLS-1$
bufferPrinter.println();
ThreadInfoBase[] threadInfoBases = dumpAllThreadsImpl(true, addSynchronizers, Integer.MAX_VALUE);
for (ThreadInfoBase currentThreadInfoBase : threadInfoBases) {
bufferPrinter.print(currentThreadInfoBase.toString());
if (addSynchronizers) {
LockInfoBase[] lockedSynchronizers = currentThreadInfoBase.getLockedSynchronizers();
bufferPrinter.printf("%n\tLocked ownable synchronizers: %d%n", //$NON-NLS-1$
Integer.valueOf(lockedSynchronizers.length));
for (LockInfoBase currentLockedSynchronizer : lockedSynchronizers) {
bufferPrinter.printf("\t- %s%n", currentLockedSynchronizer.toString()); //$NON-NLS-1$
}
}
bufferPrinter.println();
}
bufferPrinter.flush();
result = DiagnosticProperties.makeStringResult(buffer.toString());
}
return result;
}

private static native ThreadInfoBase[] dumpAllThreadsImpl(boolean lockedMonitors,
boolean lockedSynchronizers, int maxDepth);

private static DiagnosticProperties runGC() {
VM.globalGC();
Expand All @@ -128,9 +202,9 @@ private static DiagnosticProperties runGC() {

static {
commandTable = new HashMap<>();
commandTable.put(openj9.tools.attach.diagnostics.base.DiagnosticUtils.DIAGNOSTICS_GC_CLASS_HISTOGRAM,
s -> getHeapStatistics(s));
commandTable.put(openj9.tools.attach.diagnostics.base.DiagnosticUtils.DIAGNOSTICS_GC_RUN, s -> runGC());
commandTable.put(DIAGNOSTICS_GC_CLASS_HISTOGRAM, DiagnosticUtils::getHeapStatistics);
commandTable.put(DIAGNOSTICS_GC_RUN, s -> runGC());
commandTable.put(DIAGNOSTICS_THREAD_PRINT, DiagnosticUtils::getThreadInfo);
}

}

0 comments on commit 25e124d

Please sign in to comment.