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