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