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.debugger.*; 27 28 import java.util.ArrayList; 29 import java.util.List; 30 import java.util.stream.Collectors; 31 32 import jdk.test.lib.JDKToolLauncher; 33 import jdk.test.lib.Platform; 34 import jdk.test.lib.process.ProcessTools; 35 import jdk.test.lib.process.OutputAnalyzer; 36 import jdk.test.lib.Utils; 37 import jdk.test.lib.apps.LingeredApp; 38 import jdk.test.lib.Asserts; 39 40 import java.io.*; 41 import java.util.*; 42 43 /* 44 * @test 45 * @library /test/lib 46 * @modules java.base/jdk.internal.misc 47 * @modules jdk.hotspot.agent 48 * @modules jdk.hotspot.agent/sun.jvm.hotspot 49 * @modules jdk.hotspot.agent/sun.jvm.hotspot.utilities 50 * @modules jdk.hotspot.agent/sun.jvm.hotspot.oops 51 * @compile -XDignore.symbol.file=true -Xmodule:jdk.hotspot.agent 52 * -XaddExports:java.base/jdk.internal.misc=jdk.hotspot.agent 53 * -XaddExports:java.management/java.lang.management=jdk.hotspot.agent 54 * TestInstanceKlassSize.java 55 * @run main/othervm TestInstanceKlassSize 56 */ 57 58 public class TestInstanceKlassSize { 59 60 private static String getJcmdInstanceKlassSize(OutputAnalyzer output, 61 String instanceKlassName) { 62 for (String s : output.asLines()) { 63 if (s.contains(instanceKlassName)) { 64 String tokens[]; 65 System.out.println(s); 66 tokens = s.split("\\s+"); 67 return tokens[3]; 68 } 69 } 70 return null; 71 } 72 73 private static OutputAnalyzer jcmd(Long pid, 74 String... toolArgs) throws Exception { 75 ProcessBuilder processBuilder = new ProcessBuilder(); 76 JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jcmd"); 77 launcher.addToolArg(Long.toString(pid)); 78 if (toolArgs != null) { 79 for (String toolArg : toolArgs) { 80 launcher.addToolArg(toolArg); 81 } 82 } 83 84 processBuilder.command(launcher.getCommand()); 85 System.out.println( 86 processBuilder.command().stream().collect(Collectors.joining(" "))); 87 return ProcessTools.executeProcess(processBuilder); 88 } 89 90 private static void startMeWithArgs() throws Exception { 91 92 LingeredApp app = null; 93 OutputAnalyzer output = null; 94 try { 95 List<String> vmArgs = new ArrayList<String>(); 96 vmArgs.add("-XX:+UnlockDiagnosticVMOptions"); 97 vmArgs.add("-XX:+UsePerfData"); 98 vmArgs.addAll(Utils.getVmOptions()); 99 app = LingeredApp.startApp(vmArgs); 100 System.out.println ("Started LingeredApp with pid " + app.getPid()); 101 } catch (Exception ex) { 102 ex.printStackTrace(); 103 throw new RuntimeException(ex); 104 } 105 try { 106 String[] instanceKlassNames = new String[] { 107 " java.lang.Object", 108 " java.util.Vector", 109 " sun.util.PreHashedMap", 110 " java.lang.String", 111 " java.lang.Thread", 112 " java.lang.Byte", 113 }; 114 String[] toolArgs = { 115 "-XX:+UnlockDiagnosticVMOptions", 116 "-XaddExports:jdk.hotspot.agent/sun.jvm.hotspot=ALL-UNNAMED", 117 "-XaddExports:jdk.hotspot.agent/sun.jvm.hotspot.utilities=ALL-UNNAMED", 118 "-XaddExports:jdk.hotspot.agent/sun.jvm.hotspot.oops=ALL-UNNAMED", 119 "TestInstanceKlassSize", 120 Long.toString(app.getPid()) 121 }; 122 123 OutputAnalyzer jcmdOutput = jcmd( 124 app.getPid(), 125 "GC.class_stats", "VTab,ITab,OopMap,KlassBytes"); 126 ProcessBuilder processBuilder = ProcessTools 127 .createJavaProcessBuilder(toolArgs); 128 output = ProcessTools.executeProcess(processBuilder); 129 System.out.println(output.getOutput()); 130 output.shouldHaveExitValue(0); 131 132 // Check whether the size matches that which jcmd outputs 133 for (String instanceKlassName : instanceKlassNames) { 134 System.out.println ("Trying to match for" + instanceKlassName); 135 String jcmdInstanceKlassSize = getJcmdInstanceKlassSize( 136 jcmdOutput, 137 instanceKlassName); 138 for (String s : output.asLines()) { 139 if (s.contains(instanceKlassName)) { 140 Asserts.assertTrue( 141 s.contains(jcmdInstanceKlassSize), 142 "The size computed by SA for" + 143 instanceKlassName + " does not match."); 144 } 145 } 146 } 147 } finally { 148 LingeredApp.stopApp(app); 149 } 150 } 151 152 private static void SAInstanceKlassSize(int pid, 153 String[] SAInstanceKlassNames) { 154 HotSpotAgent agent = new HotSpotAgent(); 155 try { 156 agent.attach(pid); 157 } 158 catch (DebuggerException e) { 159 System.out.println(e.getMessage()); 160 System.err.println("Unable to connect to process ID: " + pid); 161 162 agent.detach(); 163 e.printStackTrace(); 164 } 165 166 for (String SAInstanceKlassName : SAInstanceKlassNames) { 167 Long size = SystemDictionaryHelper.findInstanceKlass( 168 SAInstanceKlassName).getSize(); 169 System.out.println("SA: The size of " + SAInstanceKlassName + 170 " is " + size); 171 } 172 agent.detach(); 173 } 174 175 public static void main(String[] args) throws Exception { 176 177 if (!Platform.shouldSAAttach()) { 178 System.out.println("SA attach not expected to work - test skipped."); 179 return; 180 } 181 182 if (args == null || args.length == 0) { 183 System.out.println ("No args run. Starting with args now."); 184 startMeWithArgs(); 185 } else { 186 String[] SAInstanceKlassNames = new String[] { 187 "java.lang.Object", 188 "java.util.Vector", 189 "sun.util.PreHashedMap", 190 "java.lang.String", 191 "java.lang.Thread", 192 "java.lang.Byte" 193 }; 194 SAInstanceKlassSize(Integer.parseInt(args[0]), SAInstanceKlassNames); 195 } 196 } 197 } 198