1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
|
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.io.IOException;
import java.util.Arrays;
import java.util.concurrent.CountDownLatch;
import java.util.Set;
import java.util.HashSet;
import static jdk.test.lib.Asserts.assertTrue;
/**
* @test
* @summary Tests the modules-related JDWP commands
* @library /test/lib
* @modules jdk.jdwp.agent
* @modules java.base/jdk.internal.misc
* @compile AllModulesCommandTestDebuggee.java
* @run main/othervm AllModulesCommandTest
*/
public class AllModulesCommandTest implements DebuggeeLauncher.Listener {
private DebuggeeLauncher launcher;
private JdwpChannel channel;
private CountDownLatch jdwpLatch = new CountDownLatch(1);
private Set<String> jdwpModuleNames = new HashSet<>();
private Set<String> javaModuleNames = new HashSet<>();
public static void main(String[] args) throws Throwable {
new AllModulesCommandTest().doTest();
}
private void doTest() throws Throwable {
launcher = new DebuggeeLauncher(this);
launcher.launchDebuggee();
// Await till the debuggee sends all the necessary modules info to check against
// then start the JDWP session
jdwpLatch.await();
doJdwp();
}
@Override
public void onDebuggeeModuleInfo(String modName) {
// The debuggee has sent out info about a loaded module
javaModuleNames.add(modName);
}
@Override
public void onDebuggeeSendingCompleted() {
// The debuggee has completed sending all the info
// We can start the JDWP session
jdwpLatch.countDown();
}
@Override
public void onDebuggeeError(String message) {
System.err.println("Debuggee error: '" + message + "'");
System.exit(1);
}
private void doJdwp() throws Exception {
try {
// Establish JDWP socket connection
channel = new JdwpChannel();
channel.connect();
// Send out ALLMODULES JDWP command
// and verify the reply
JdwpAllModulesReply reply = new JdwpAllModulesCmd().send(channel);
assertReply(reply);
for (int i = 0; i < reply.getModulesCount(); ++i) {
long modId = reply.getModuleId(i);
// For each module reported by JDWP get its name using the JDWP NAME command
// and store the reply
String modName = getModuleName(modId);
System.out.println("i=" + i + ", modId=" + modId + ", modName=" + modName);
if (modName != null) { // JDWP reports unnamed modules, ignore them
jdwpModuleNames.add(modName);
}
// Assert the CLASSLOADER commands
assertClassLoader(modId, modName);
}
System.out.println("Module names reported by JDWP: " + Arrays.toString(jdwpModuleNames.toArray()));
System.out.println("Module names reported by Java: " + Arrays.toString(javaModuleNames.toArray()));
// Modules reported by the JDWP should be the same as reported by the Java API
if (!jdwpModuleNames.equals(javaModuleNames)) {
throw new RuntimeException("Modules info reported by Java API differs from that reported by JDWP.");
} else {
System.out.println("Test passed!");
}
} finally {
launcher.terminateDebuggee();
try {
new JdwpExitCmd(0).send(channel);
channel.disconnect();
} catch (Exception x) {
}
}
}
private String getModuleName(long modId) throws IOException {
JdwpModNameReply reply = new JdwpModNameCmd(modId).send(channel);
assertReply(reply);
return reply.getModuleName();
}
private void assertReply(JdwpReply reply) {
// Simple assert for any JDWP reply
if (reply.getErrorCode() != 0) {
throw new RuntimeException("Unexpected reply error code " + reply.getErrorCode() + " for reply " + reply);
}
}
private void assertClassLoader(long modId, String modName) throws IOException {
// Verify that the module classloader id is valid
JdwpClassLoaderReply reply = new JdwpClassLoaderCmd(modId).send(channel);
assertReply(reply);
long moduleClassLoader = reply.getClassLoaderId();
assertTrue(moduleClassLoader >= 0, "bad classloader refId " + moduleClassLoader + " for module '" + modName + "', moduleId=" + modId);
String clsModName = getModuleName(modId);
if ("java.base".equals(clsModName)) {
// For the java.base module, because there will be some loaded classes, we can verify
// that some of the loaded classes do report the java.base module as the module they belong to
assertGetModule(moduleClassLoader, modId);
}
}
private void assertGetModule(long moduleClassLoader, long modId) throws IOException {
// Get all the visible classes for the module classloader
JdwpVisibleClassesReply visibleClasses = new JdwpVisibleClassesCmd(moduleClassLoader).send(channel);
assertReply(visibleClasses);
boolean moduleFound = false;
for (long clsId : visibleClasses.getVisibleClasses()) {
// For each visible class get the module the class belongs to
JdwpModuleReply modReply = new JdwpModuleCmd(clsId).send(channel);
assertReply(modReply);
long clsModId = modReply.getModuleId();
// At least one of the visible classes should belong to our module
if (modId == clsModId) {
moduleFound = true;
break;
}
}
assertTrue(moduleFound, "None of the visible classes for the classloader of the module " + getModuleName(modId) + " reports the module as its own");
}
}
|