1 /* 2 * Copyright (c) 2015, 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 /* 25 * @test 26 * @summary Test of diagnostic command VM.class_hierarchy 27 * @library /test/lib 28 * @modules java.base/jdk.internal.misc 29 * java.compiler 30 * java.management 31 * jdk.jvmstat/sun.jvmstat.monitor 32 * @run testng ClassHierarchyTest 33 */ 34 35 import org.testng.annotations.Test; 36 import org.testng.Assert; 37 38 import jdk.test.lib.process.OutputAnalyzer; 39 import jdk.test.lib.dcmd.CommandExecutor; 40 import jdk.test.lib.dcmd.JMXExecutor; 41 42 import java.io.File; 43 import java.io.FileInputStream; 44 import java.io.IOException; 45 import java.nio.ByteBuffer; 46 import java.nio.channels.FileChannel; 47 import java.util.Iterator; 48 import java.util.regex.Matcher; 49 import java.util.regex.Pattern; 50 51 public class ClassHierarchyTest { 52 53 // $> jcmd DcmdTestClass VM.class_hierarchy DcmdTestClass | grep DcmdTestClass\$\$Lambda 54 // |--DcmdTestClass$$Lambda$1/4081552/0xa529fbb0 55 56 // > VM.class_hierarchy DcmdBaseClass 57 // java.lang.Object/null 58 // |--DcmdBaseClass/0xa4abcd48 59 60 // > VM.class_hierarchy DcmdBaseClass -s 61 // java.lang.Object/null 62 // |--DcmdBaseClass/0xa4abcd48 63 // | |--DcmdTestClass/0xa4abcd48 64 65 // > VM.class_hierarchy DcmdBaseClass -i -s 66 // java.lang.Object/null 67 // |--DcmdBaseClass/0xa4abcd48 68 // | implements Intf2/0xa4abcd48 (declared intf) 69 // | implements Intf1/0xa4abcd48 (inherited intf) 70 // | |--DcmdTestClass/0xa4abcd48 71 // | | implements Intf1/0xa4abcd48 (inherited intf) 72 // | | implements Intf2/0xa4abcd48 (inherited intf) 73 74 static Pattern expected_lambda_line = 75 Pattern.compile("\\|--DcmdTestClass\\$\\$Lambda.*"); 76 77 static Pattern expected_lines[] = { 78 Pattern.compile("java.lang.Object/null"), 79 Pattern.compile("\\|--DcmdBaseClass/0x(\\p{XDigit}*)"), 80 Pattern.compile("\\| implements Intf2/0x(\\p{XDigit}*) \\(declared intf\\)"), 81 Pattern.compile("\\| implements Intf1/0x(\\p{XDigit}*) \\(inherited intf\\)"), 82 Pattern.compile("\\| \\|--DcmdTestClass/0x(\\p{XDigit}*)"), 83 Pattern.compile("\\| \\| implements Intf1/0x(\\p{XDigit}*) \\(inherited intf\\)"), 84 Pattern.compile("\\| \\| implements Intf2/0x(\\p{XDigit}*) \\(inherited intf\\)") 85 }; 86 87 public void run(CommandExecutor executor) throws ClassNotFoundException { 88 OutputAnalyzer output; 89 Iterator<String> lines; 90 int i; 91 92 // Load our test class whose hierarchy we will print. 93 Class<?> c = Class.forName("DcmdTestClass"); 94 95 // Verify the presence of the lamba anonymous class 96 output = executor.execute("VM.class_hierarchy"); 97 lines = output.asLines().iterator(); 98 Boolean foundMatch = false; 99 while (lines.hasNext()) { 100 String line = lines.next(); 101 Matcher m = expected_lambda_line.matcher(line); 102 if (m.matches()) { 103 foundMatch = true; 104 break; 105 } 106 } 107 if (!foundMatch) { 108 Assert.fail("Failed to find lamda class"); 109 } 110 111 // Verify the output for the simple hierachry of just DcmdBaseClass. 112 output = executor.execute("VM.class_hierarchy DcmdBaseClass"); 113 lines = output.asLines().iterator(); 114 i = 0; 115 while (lines.hasNext()) { 116 String line = lines.next(); 117 Matcher m = expected_lines[i].matcher(line); 118 i++; 119 if (!m.matches()) { 120 Assert.fail("Failed to match line #" + i + ": " + line); 121 } 122 // Should only be two lines of output in this form. 123 if (i == 2) break; 124 } 125 if (lines.hasNext()) { 126 String line = lines.next(); 127 Assert.fail("Unexpected dcmd output: " + line); 128 } 129 130 // Verify the output for the full hierarchy of DcmdBaseClass, but without interfaces. 131 output = executor.execute("VM.class_hierarchy DcmdBaseClass -s"); 132 lines = output.asLines().iterator(); 133 i = 0; 134 while (lines.hasNext()) { 135 String line = lines.next(); 136 Matcher m = expected_lines[i].matcher(line); 137 i++; 138 if (!m.matches()) { 139 Assert.fail("Failed to match line #" + i + ": " + line); 140 } 141 // "implements" lines should not be in this output. 142 if (i == 2 || i == 4) i += 2; 143 } 144 if (lines.hasNext()) { 145 String line = lines.next(); 146 Assert.fail("Unexpected dcmd output: " + line); 147 } 148 149 // Verify the output for the full hierarchy of DcmdBaseClass, including interfaces. 150 output = executor.execute("VM.class_hierarchy DcmdBaseClass -i -s"); 151 lines = output.asLines().iterator(); 152 i = 0; 153 String classLoaderAddr = null; 154 while (lines.hasNext()) { 155 String line = lines.next(); 156 Matcher m = expected_lines[i].matcher(line); 157 i++; 158 if (!m.matches()) { 159 Assert.fail("Failed to match line #" + i + ": " + line); 160 } 161 if (i == 2) { 162 // Fetch the ClassLoader address, which should be the same in 163 // subsequent lines. 164 classLoaderAddr = m.group(1); 165 System.out.println(classLoaderAddr); 166 } else if (i > 2) { 167 if (!classLoaderAddr.equals(m.group(1))) { 168 Assert.fail("Classloader address didn't match on line #" 169 + i + ": " + line); 170 } 171 } 172 if (i == expected_lines.length) break; 173 } 174 if (lines.hasNext()) { 175 String line = lines.next(); 176 Assert.fail("Unexpected dcmd output: " + line); 177 } 178 } 179 180 @Test 181 public void jmx() throws ClassNotFoundException { 182 run(new JMXExecutor()); 183 } 184 } 185 186 interface Intf1 { 187 } 188 189 interface Intf2 extends Intf1 { 190 } 191 192 class DcmdBaseClass implements Intf2 { 193 } 194 195 class DcmdTestClass extends DcmdBaseClass { 196 static { 197 // Force creation of anonymous class (for the lambdaform). 198 Runnable r = () -> System.out.println("Hello"); 199 r.run(); 200 } 201 }