--- /dev/null 2014-12-10 11:56:21.778113487 -0800 +++ new/test/serviceability/dcmd/ClassHierarchyTest.java 2015-02-10 18:55:34.000000000 -0800 @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2015, 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. + */ + +/* + * @test + * + * @build ClassHierarchyTest DcmdUtil + * @run main ClassHierarchyTest + */ + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.StringReader; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class ClassHierarchyTest { + + // $> jcmd DcmdTestClass VM.class_hierarchy DcmdTestClass | grep DcmdTestClass\$\$Lambda + // |--DcmdTestClass$$Lambda$1/4081552/0xa529fbb0 + + // > VM.class_hierarchy DcmdBaseClass : + // java.lang.Object/null + // |--DcmdBaseClass/0xa4abcd48 + + // > VM.class_hierarchy DcmdBaseClass -s : + // java.lang.Object/null + // |--DcmdBaseClass/0xa4abcd48 + // | |--DcmdTestClass/0xa4abcd48 + + // > VM.class_hierarchy DcmdBaseClass -i -s : + // java.lang.Object/null + // |--DcmdBaseClass/0xa4abcd48 + // | implements Intf2/0xa4abcd48 (declared intf) + // | implements Intf1/0xa4abcd48 (inherited intf) + // | |--DcmdTestClass/0xa4abcd48 + // | | implements Intf1/0xa4abcd48 (inherited intf) + // | | implements Intf2/0xa4abcd48 (inherited intf) + + static Pattern lambdaLine = + Pattern.compile("\\|--DcmdTestClass\\$\\$Lambda.*"); + + static Pattern lines[] = { + Pattern.compile("java.lang.Object/null"), + Pattern.compile("\\|--DcmdBaseClass/0x(\\p{XDigit}*)"), + Pattern.compile("\\| implements Intf2/0x(\\p{XDigit}*) \\(declared intf\\)"), + Pattern.compile("\\| implements Intf1/0x(\\p{XDigit}*) \\(inherited intf\\)"), + Pattern.compile("\\| \\|--DcmdTestClass/0x(\\p{XDigit}*)"), + Pattern.compile("\\| \\| implements Intf1/0x(\\p{XDigit}*) \\(inherited intf\\)"), + Pattern.compile("\\| \\| implements Intf2/0x(\\p{XDigit}*) \\(inherited intf\\)") + }; + + public static void main(String arg[]) throws Exception { + String result; + BufferedReader r; + int i; + String line; + + // Load our test class whose hierarchy we will print. + Class c = Class.forName("DcmdTestClass"); + + // Verify the presence of the lamba anonymous class + result = DcmdUtil.executeDcmd("VM.class_hierarchy"); + r = new BufferedReader(new StringReader(result)); + Boolean foundMatch = false; + while ((line = r.readLine()) != null) { + Matcher m = lambdaLine.matcher(line); + if (m.matches()) { + foundMatch = true; + break; + } + } + if (!foundMatch) { + throw new Exception("Failed to find lamda class"); + } + + // Verify the output for the simple hierachry of just DcmdBaseClass. + result = DcmdUtil.executeDcmd("VM.class_hierarchy", "DcmdBaseClass"); + r = new BufferedReader(new StringReader(result)); + i = 0; + while ((line = r.readLine()) != null) { + Matcher m = lines[i].matcher(line); + i++; + if (!m.matches()) { + throw new Exception("Failed to match line #" + i + ": " + line); + } + // Should only be two lines of output in this form. + if (i == 2) break; + } + if ((line = r.readLine()) != null) { + throw new Exception("Unexpected dcmd output: " + line); + } + + // Verify the output for the full hierarchy of DcmdBaseClass, but without interfaces. + result = DcmdUtil.executeDcmd("VM.class_hierarchy", "DcmdBaseClass -s"); + r = new BufferedReader(new StringReader(result)); + i = 0; + while ((line = r.readLine()) != null) { + Matcher m = lines[i].matcher(line); + i++; + if (!m.matches()) { + throw new Exception("Failed to match line #" + i + ": " + line); + } + // "implements" lines should not be in this output. + if (i == 2 || i == 4) i += 2; + } + if ((line = r.readLine()) != null) { + throw new Exception("Unexpected dcmd output: " + line); + } + + // Verify the output for the full hierarchy of DcmdBaseClass, including interfaces. + result = DcmdUtil.executeDcmd("VM.class_hierarchy", "DcmdBaseClass -i -s"); + r = new BufferedReader(new StringReader(result)); + i = 0; + String classLoaderAddr = null; + while ((line = r.readLine()) != null) { + Matcher m = lines[i].matcher(line); + i++; + if (!m.matches()) { + throw new Exception("Failed to match line #" + i + ": " + line); + } + if (i == 2) { + // Fetch the ClassLoader address, which should be the same in + // subsequent lines. + classLoaderAddr = m.group(1); + System.out.println(classLoaderAddr); + } else if (i > 2) { + if (!classLoaderAddr.equals(m.group(1))) { + throw new Exception("Classloader address didn't match on line #" + + i + ": " + line); + } + } + if (i == lines.length) break; + } + if ((line = r.readLine()) != null) { + throw new Exception("Unexpected dcmd output: " + line); + } + + } +} + +interface Intf1 { +} + +interface Intf2 extends Intf1 { +} + +class DcmdBaseClass implements Intf2 { +} + +class DcmdTestClass extends DcmdBaseClass { + static { + // Force creation of anonymous class (for the lambdaform). + Runnable r = () -> System.out.println("Hello"); + r.run(); + } +}