1 # Mission Control 2 3 Mission Control is an open source production time profiling and diagnostics tool for Java. 4 5 Builds of Mission Control can currently be found in the Oracle JDK on supported platforms and in the Eclipse marketplace. 6 7 For more information on Mission Control, see http://www.oracle.com/missioncontrol. 8 9 ### Core API Features 10 11 * Core APIs for parsing and processing Java flight recordings 12 13 * Core API can *read* recordings from JDK 7 and above 14 15 * Core API can *run* on JDK 7 and above 16 17 * Core API contains a framework for handling units of measurement and physical quantities 18 19 * Core API supports headless analysis of Java flight recordings 20 21 22 ### Application Features 23 24 * An application supporting framework for hosting various useful Java tools 25 26 * A tool for visualizing the contents of Java flight recordings, and the results of an automated analysis of the contents 27 28 * A JMX Console 29 30 * A tool for heap waste analysis 31 32 33 ### Core API Example 34 35 Example for producing an HTML report from the command line: 36 37 ```bash 38 java -cp <the built core jars> org.openjdk.jmc.flightrecorder.rules.report.html.JfrHtmlRulesReport <file> [<outputfile>] 39 ``` 40 41 42 Example for finding the standard deviation for the java monitor events in a recording: 43 44 ```java 45 import java.io.File; 46 47 import org.openjdk.jmc.common.IDisplayable; 48 import org.openjdk.jmc.common.item.Aggregators; 49 import org.openjdk.jmc.common.item.IItemCollection; 50 import org.openjdk.jmc.common.item.ItemFilters; 51 import org.openjdk.jmc.common.unit.IQuantity; 52 import org.openjdk.jmc.flightrecorder.JfrAttributes; 53 import org.openjdk.jmc.flightrecorder.JfrLoaderToolkit; 54 import org.openjdk.jmc.flightrecorder.jdk.JdkTypeIDs; 55 56 /** 57 * Finds out the standard deviation for the java monitor enter events. 58 */ 59 public class LoadRecording { 60 public static void main(String[] args) throws Exception { 61 IItemCollection events = JfrLoaderToolkit.loadEvents(new File(args[0])); 62 IQuantity aggregate = events.apply(ItemFilters.type(JdkTypeIDs.MONITOR_ENTER)) 63 .getAggregate(Aggregators.stddev(JfrAttributes.DURATION)); 64 65 System.out.println("The standard deviation for the Java monitor enter events was " 66 + aggregate.displayUsing(IDisplayable.AUTO)); 67 } 68 } 69 ``` 70 71 72 Example for programmatically running the rules: 73 74 ```java 75 import java.io.File; 76 import java.util.concurrent.RunnableFuture; 77 78 import org.example.util.DemoToolkit; 79 import org.openjdk.jmc.common.item.IItemCollection; 80 import org.openjdk.jmc.common.util.IPreferenceValueProvider; 81 import org.openjdk.jmc.flightrecorder.JfrLoaderToolkit; 82 import org.openjdk.jmc.flightrecorder.rules.IRule; 83 import org.openjdk.jmc.flightrecorder.rules.Result; 84 import org.openjdk.jmc.flightrecorder.rules.RuleRegistry; 85 86 public class RunRulesOnFileSimple { 87 public static void main(String[] args) throws Exception { 88 File recording = DemoToolkit.verifyRecordingArgument(RunRulesOnFileSimple.class, args); 89 IItemCollection events = JfrLoaderToolkit.loadEvents(recording); 90 91 for (IRule rule : RuleRegistry.getRules()) { 92 RunnableFuture<Result> future = rule.evaluate(events, IPreferenceValueProvider.DEFAULT_VALUES); 93 future.run(); 94 Result result = future.get(); 95 if (result.getScore() > 50) { 96 System.out.println(String.format("[Score: %3.0f] Rule ID: %s, Rule name: %s, Short description: %s", 97 result.getScore(), result.getRule().getId(), result.getRule().getName(), 98 result.getShortDescription())); 99 } 100 } 101 } 102 } 103 ``` 104 105 106 Example for programmatically running rules in parallel (requires JDK8): 107 108 ```java 109 import java.io.File; 110 import java.util.List; 111 import java.util.concurrent.ExecutionException; 112 import java.util.concurrent.Executor; 113 import java.util.concurrent.Executors; 114 import java.util.concurrent.RunnableFuture; 115 import java.util.stream.Collectors; 116 import java.util.stream.Stream; 117 118 import org.openjdk.jmc.common.item.IItemCollection; 119 import org.openjdk.jmc.common.util.IPreferenceValueProvider; 120 import org.openjdk.jmc.flightrecorder.JfrLoaderToolkit; 121 import org.openjdk.jmc.flightrecorder.rules.IRule; 122 import org.openjdk.jmc.flightrecorder.rules.Result; 123 import org.openjdk.jmc.flightrecorder.rules.RuleRegistry; 124 125 /** 126 * Runs the rules on the events in the specified file in parallel, then prints 127 * them in order of descending score. 128 */ 129 public class RunRulesOnFile { 130 private final static Executor EXECUTOR = Executors 131 .newFixedThreadPool(Runtime.getRuntime().availableProcessors() - 1); 132 private static int limit; 133 134 public static void main(String[] args) throws Exception { 135 if (args.length == 0) { 136 System.out.println( 137 "Usage: RunRulesOnFile <recording file> [<limit>]\n\tThe recording file must be a flight recording from JDK 7 or above. The limit, if set, will only report rules triggered with a score higher or equal than the limit."); 138 System.exit(2); 139 } 140 IItemCollection events = JfrLoaderToolkit.loadEvents(new File(args[0])); 141 if (args.length > 1) { 142 limit = Integer.parseInt(args[1]); 143 } 144 Stream<RunnableFuture<Result>> resultFutures = RuleRegistry.getRules().stream() 145 .map((IRule r) -> evaluate(r, events)); 146 List<Result> results = resultFutures.parallel().map((RunnableFuture<Result> runnable) -> get(runnable)) 147 .collect(Collectors.toList()); 148 results.sort((Result r1, Result r2) -> Double.compare(r2.getScore(), r1.getScore())); 149 results.stream().forEach(RunRulesOnFile::printResult); 150 } 151 152 public static RunnableFuture<Result> evaluate(IRule rule, IItemCollection events) { 153 RunnableFuture<Result> evaluation = rule.evaluate(events, IPreferenceValueProvider.DEFAULT_VALUES); 154 EXECUTOR.execute(evaluation); 155 return evaluation; 156 } 157 158 public static Result get(RunnableFuture<Result> resultFuture) { 159 try { 160 return resultFuture.get(); 161 } catch (InterruptedException | ExecutionException e) { 162 e.printStackTrace(); 163 } 164 return null; 165 } 166 167 private static void printResult(Result result) { 168 if (result.getScore() >= limit) { 169 System.out.printf("(%.0f) [%s]: %s\nDetails:\n%s\n============<End of Result>============\n", 170 result.getScore(), result.getRule().getId(), result.getShortDescription(), 171 result.getLongDescription() == null ? "<no description>" : result.getLongDescription()); 172 } 173 } 174 } 175 ``` 176 177 ## Building Mission Control from Source 178 179 Prerequisites for building Mission Control: 180 1. Install JDK 8, and make sure it is the JDK in use (java -version) 181 182 2. Install Maven (version 3.3.x. or above) 183 184 First get third party dependencies into a local p2 repo and make it available on localhost: 185 186 ```bash 187 cd missioncontrolfolder/releng/third-party 188 mvn p2:site 189 mvn jetty:run 190 ``` 191 192 Then in another terminal (in the project root): 193 194 ```bash 195 cd core 196 mvn install 197 cd ../ 198 mvn package 199 ``` 200 Note that you may need to define proxy settings if you happen to be behind a firewall. In your ~/.m2/settings.xml file (if you have none, simply create one), add: 201 202 ```xml 203 <settings> 204 <proxies> 205 <proxy> 206 <id>http-proxy</id> 207 <active>true</active> 208 <protocol>http</protocol> 209 <host>my.proxy.example.org</host> 210 <port>80</port> 211 <nonProxyHosts>localhost|*.example.org</nonProxyHosts> 212 </proxy> 213 <proxy> 214 <id>https-proxy</id> 215 <active>true</active> 216 <protocol>https</protocol> 217 <host>my.proxy.example.org</host> 218 <port>80</port> 219 <nonProxyHosts>localhost|*.example.org</nonProxyHosts> 220 </proxy> 221 </proxies> 222 </settings> 223 224 ``` 225 226 ## Running Tests 227 To run the unit tests: 228 229 ```bash 230 mvn verify 231 ``` 232 233 To run the UI tests: 234 235 > Currently, in order to run UI tests you need to supply the Jemmy UI testing libraries yourself. These can be built from source available at the mercurial repository at http://hg.openjdk.java.net/code-tools/jemmy/v3/. 236 237 >1. Create a directory on your local drive where you wish to build the Jemmy libraries. 238 >2. In a terminal, when in the newly created directory, issue `hg clone http://hg.openjdk.java.net/code-tools/jemmy/v3/`. If you don't have a Mercurial client you can download the code from http://hg.openjdk.java.net/code-tools/jemmy/v3/archive/tip.zip (or .gz or .bz2). 239 >3. Build Jemmy by issuing `mvn clean package`. Adding `-DskipTests` makes sure that UI tests that might fail won't stop the packaging. 240 >4. Copy the resulting jar files from core/JemmyCore/target, core/JemmyAWTInput/target, core/JemmyBrowser/target and SWT/JemmySWT/target to \[jmc_repo_dir\]/application/uitests/org.openjdk.jmc.test.jemmy/lib/ (create the lib directory first if it does not exist). 241 242 >(As soon as Jemmy is published on Maven Central, this manual build step will be removed.) 243 244 ```bash 245 mvn verify -P uitests 246 ``` 247 Note that the UI tests will take some time to run, and that you need to stop interacting with your computer for the duration of the tests. 248 249 Spotbugs can take some time to run. If you are only interested in the test results, you can skip running spotbugs by setting `-Dspotbugs.skip=true`. 250 251 For example: 252 253 ```bash 254 mvn verify -P uitests -Dspotbugs.skip=true 255 ``` 256 257 ## Filtering Test Runs 258 Aside from the from the simple -test Maven flag test classes that should be run/not run can be specified by means of the system properties "test.includes" and/or "test.excludes". Multiple patterns can be specified by comma separation. 259 260 For example: 261 262 ```bash 263 mvn verify -Dtest.includes=**/*TestRulesWithJfr*,**/*StacktraceModelTest* 264 ``` 265 266 When specifying both test.includes and "test.excludes" the test.excludes takes precedence and filters out tests that also are matched by "test.includes". 267 268 For example: 269 270 ```bash 271 mvn verify -P uitests -Dtest.includes=**/*SystemTabTest*,**/*TestRulesWithJfr*,**/*StacktraceModelTest* -Dtest.excludes=**/*ModelTest* 272 ``` 273 274 The above will not run StacktraceModelTest, as that is also matched by "test.excludes". 275 276 Note that if UI-tests are supposed to be part of the filtered run the "uitests" profile needs to be specified as well. Otherwise the UI won't start up and so the tests fail. 277 278 ## Running the Locally Built JMC 279 The built JMC will end up in the `target` folder in the root. To run it, go to `target/products/org.openjdk.jmc/<platform>` to find the launcher. Don't forget to override the vm flag with the JVM you wish to use for running JMC. 280 281 Here is an example for Mac OS X: 282 283 ```bash 284 target/products/org.openjdk.jmc/macosx/cocoa/x86_64/JDK\ Mission\ Control.app/Contents/MacOS/jmc -vm $JAVA_HOME/bin 285 ``` 286 287 Here is an Linux example: 288 289 ```bash 290 target/products/org.openjdk.jmc/linux/gtk/x86_64/jmc -vm $JAVA_HOME/bin 291 ``` 292 293 And here is an example for Windows x64: 294 295 ```bash 296 missioncontrol\target\products\org.openjdk.jmc\win32\win32\x86_64\jmc.exe -vm %JAVA_HOME%\bin 297 ``` 298 299 ## Setting Up for Development and Launching in Eclipse 300 First make sure that you have installed the Mercurial Plug-in for Eclipse (MercurialEclipse). It can be installed from the Eclipse Marketplace (Help | Eclipse Marketplace...). At the time of writing, version 2.2 was the most recent one. 301 302 1. First ensure that you have started the jetty server in the first step of building JMC. 303 2. Next open (File | Open...) the Eclipse target platform of interest, for example releng/platform-definitions/platform-definition-photon/platform.target 304 3. In the upper right corner of the platform editor that opens, click the link "Set as Active Target Platform" 305 4. Import the projects you are interested in (core and/or application) into a recent Eclipse. 306 5. If importing the application projects, make sure you create a user library (Preferences | Java/Build Path/User Libraries) named JMC_JDK, and add (Add External JARs...) the following JARs from a JDK 8 (u40 or above) to the User Library: 307 - tools.jar (<JDK>/lib/tools.jar) 308 - jconsole.jar (<JDK>/lib/jconsole.jar) 309 - jfxswt.jar (<JDK>/jre/lib/jfxswt.jar) 310 - jfxrt.jar (<JDK>/jre/lib/ext/jfxrt.jar) 311 312 Note that importing configuration/ide/eclipse as an Eclipse project should automatically make the development launchers available to you. 313 314 ## License 315 The Mission Control source code is made available under the Universal Permissive License (UPL), Version 1.0 or a BSD-style license, alternatively. The full open source license text is available at license/LICENSE.txt in the JMC project. 316 317 ## About 318 Mission Control is an open source project of the [OpenJDK](http://openjdk.java.net/). 319 The Mission Control project originated from the JRockit JVM project.