1 /* 2 * Copyright (c) 2015, 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 sun.jvm.hotspot.HotSpotAgent; 25 import sun.jvm.hotspot.utilities.SystemDictionaryHelper; 26 import sun.jvm.hotspot.oops.InstanceKlass; 27 import sun.jvm.hotspot.debugger.*; 28 29 import jdk.test.lib.JDKToolLauncher; 30 import jdk.test.lib.JDKToolFinder; 31 import jdk.test.lib.Platform; 32 import jdk.test.lib.ProcessTools; 33 import jdk.test.lib.OutputAnalyzer; 34 import jdk.test.lib.Utils; 35 import jdk.test.lib.Asserts; 36 37 /* 38 * @test 39 * @library /test/lib/share/classes 40 * @library /testlibrary 41 * @build jdk.test.lib.* 42 * @build jdk.test.lib.apps.* 43 * @modules java.base/jdk.internal.misc 44 * @modules jdk.hotspot.agent 45 * @modules jdk.hotspot.agent/sun.jvm.hotspot 46 * @modules jdk.hotspot.agent/sun.jvm.hotspot.utilities 47 * @modules jdk.hotspot.agent/sun.jvm.hotspot.oops 48 * @compile -XDignore.symbol.file=true -Xmodule:jdk.hotspot.agent TestInstanceKlassSizeForInterface.java 49 * @run main/othervm TestInstanceKlassSizeForInterface 50 */ 51 52 interface Language { 53 static final long nbrOfWords = 99999; 54 public abstract long getNbrOfWords(); 55 } 56 57 class ParselTongue implements Language { 58 public long getNbrOfWords() { 59 return nbrOfWords * 4; 60 } 61 } 62 63 public class TestInstanceKlassSizeForInterface { 64 65 private static void SAInstanceKlassSize(int pid, 66 String[] instanceKlassNames) { 67 68 HotSpotAgent agent = new HotSpotAgent(); 69 try { 70 agent.attach((int)pid); 71 } 72 catch (DebuggerException e) { 73 System.out.println(e.getMessage()); 74 System.err.println("Unable to connect to process ID: " + pid); 75 76 agent.detach(); 77 e.printStackTrace(); 78 } 79 80 for (String instanceKlassName : instanceKlassNames) { 81 InstanceKlass iKlass = SystemDictionaryHelper.findInstanceKlass( 82 instanceKlassName); 83 System.out.println("SA: The size of " + instanceKlassName + 84 " is " + iKlass.getSize()); 85 } 86 agent.detach(); 87 } 88 89 private static String getJcmdInstanceKlassSize(OutputAnalyzer output, 90 String instanceKlassName) { 91 for (String s : output.asLines()) { 92 if (s.contains(instanceKlassName)) { 93 String tokens[]; 94 System.out.println(s); 95 tokens = s.split("\\s+"); 96 return tokens[3]; 97 } 98 } 99 return null; 100 } 101 102 private static void createAnotherToAttach( 103 String[] instanceKlassNames) throws Exception { 104 105 ProcessBuilder pb = new ProcessBuilder(); 106 107 // Grab the pid from the current java process and pass it 108 String[] toolArgs = { 109 "-XX:+UnlockDiagnosticVMOptions", 110 "-XaddExports:jdk.hotspot.agent/sun.jvm.hotspot=ALL-UNNAMED", 111 "-XaddExports:jdk.hotspot.agent/sun.jvm.hotspot.utilities=ALL-UNNAMED", 112 "-XaddExports:jdk.hotspot.agent/sun.jvm.hotspot.oops=ALL-UNNAMED", 113 "TestInstanceKlassSizeForInterface", 114 Long.toString(ProcessTools.getProcessId()) 115 }; 116 117 pb.command(new String[] { 118 JDKToolFinder.getJDKTool("jcmd"), 119 Long.toString(ProcessTools.getProcessId()), 120 "GC.class_stats", 121 "VTab,ITab,OopMap,KlassBytes" 122 } 123 ); 124 125 // Start a new process to attach to the current process 126 ProcessBuilder processBuilder = ProcessTools 127 .createJavaProcessBuilder(toolArgs); 128 OutputAnalyzer SAOutput = ProcessTools.executeProcess(processBuilder); 129 System.out.println(SAOutput.getOutput()); 130 131 OutputAnalyzer jcmdOutput = new OutputAnalyzer(pb.start()); 132 System.out.println(jcmdOutput.getOutput()); 133 134 // Match the sizes from both the output streams 135 for (String instanceKlassName : instanceKlassNames) { 136 System.out.println ("Trying to match for " + instanceKlassName); 137 String jcmdInstanceKlassSize = getJcmdInstanceKlassSize( 138 jcmdOutput, 139 instanceKlassName); 140 for (String s : SAOutput.asLines()) { 141 if (s.contains(instanceKlassName)) { 142 Asserts.assertTrue( 143 s.contains(jcmdInstanceKlassSize), 144 "The size computed by SA for " + 145 instanceKlassName + " does not match."); 146 } 147 } 148 } 149 } 150 151 public static void main (String... args) throws Exception { 152 String[] instanceKlassNames = new String[] { 153 "Language", 154 "ParselTongue", 155 "TestInstanceKlassSizeForInterface$1" 156 }; 157 158 if (!Platform.shouldSAAttach()) { 159 System.out.println( 160 "SA attach not expected to work - test skipped."); 161 return; 162 } 163 164 if ( args == null || args.length == 0 ) { 165 ParselTongue lang = new ParselTongue(); 166 167 Language ventro = new Language() { 168 public long getNbrOfWords() { 169 return nbrOfWords * 8; 170 } 171 }; 172 173 // Not tested at this point. The test needs to be enhanced 174 // later to test for the sizes of the Lambda MetaFactory 175 // generated anonymous classes too. (After JDK-8160228 gets 176 // fixed.) 177 Runnable r2 = () -> System.out.println("Hello world!"); 178 r2.run(); 179 180 createAnotherToAttach(instanceKlassNames); 181 } else { 182 SAInstanceKlassSize(Integer.parseInt(args[0]), instanceKlassNames); 183 } 184 } 185 }