Add visualVM plugin

This commit is contained in:
Martin Hare Robertson 2010-07-11 14:29:39 +01:00
parent ab25eeb255
commit e9d298c4df
35 changed files with 533 additions and 23 deletions

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- You may freely edit this file. See harness/README in the NetBeans platform -->
<!-- for some information on what you could do (e.g. targets to override). -->
<!-- If you delete this file and reopen the project it will be recreated. -->
<project name="org.intrace.visualvm" default="netbeans" basedir=".">
<description>Builds, tests, and runs the project org.intrace.visualvm.</description>
<import file="nbproject/build-impl.xml"/>
<target name="init" depends="basic-init,files-init,build-init,-javac-init,-post-init"/>
<target name="-post-init" depends="build-libs"/>
<target name="build-libs">
<ant dir="${basedir}/../org.intrace/" target="jar"/>
<copy todir="${basedir}/release/modules/ext">
<fileset dir="${basedir}/../org.intrace/build/jars">
<include name="intrace-agent.jar"/>
<include name="intrace-client-gui-linux.jar"/>
<include name="intrace-client-gui-win.jar"/>
</fileset>
</copy>
<echo message="${cp.extra}" />
</target>
</project>

View File

@ -0,0 +1,7 @@
Manifest-Version: 1.0
OpenIDE-Module: org.intrace.visualvm
OpenIDE-Module-Install: org/intrace/visualvm/Installer.class
OpenIDE-Module-Layer: org/intrace/visualvm/layer.xml
OpenIDE-Module-Localizing-Bundle: org/intrace/visualvm/Bundle.properties
OpenIDE-Module-Specification-Version: 1.0

View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
*** GENERATED FROM project.xml - DO NOT EDIT ***
*** EDIT ../build.xml INSTEAD ***
-->
<project name="org.intrace.visualvm-impl" basedir="..">
<fail message="Please build using Ant 1.7.1 or higher.">
<condition>
<not>
<antversion atleast="1.7.1"/>
</not>
</condition>
</fail>
<property file="nbproject/private/platform-private.properties"/>
<property file="nbproject/platform.properties"/>
<macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2">
<attribute name="name"/>
<attribute name="value"/>
<sequential>
<property name="@{name}" value="${@{value}}"/>
</sequential>
</macrodef>
<macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-project/2">
<attribute name="property"/>
<attribute name="value"/>
<sequential>
<property name="@{property}" value="@{value}"/>
</sequential>
</macrodef>
<property file="${user.properties.file}"/>
<nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
<nbmproject2:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
<nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
<fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness).">
<condition>
<not>
<contains string="${cluster.path.evaluated}" substring="platform"/>
</not>
</condition>
</fail>
<import file="${harness.dir}/build.xml"/>
</project>

View File

@ -0,0 +1,8 @@
build.xml.data.CRC32=bb7a3013
build.xml.script.CRC32=6b6e80f6
build.xml.stylesheet.CRC32=a56c6a5b@1.42.1
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
nbproject/build-impl.xml.data.CRC32=c6db8612
nbproject/build-impl.xml.script.CRC32=7cbc4f92
nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.42.1

View File

@ -0,0 +1,5 @@
cluster.path=\
${nbplatform.active.dir}/platform:\
${nbplatform.active.dir}/profiler:\
${nbplatform.active.dir}/visualvm
nbplatform.active=VisualVM_1.2.2

View File

@ -0,0 +1 @@
user.properties.file=C:\\Documents and Settings\\mch50\\.netbeans\\6.9\\build.properties

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project-private xmlns="http://www.netbeans.org/ns/project-private/1">
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/1"/>
</project-private>

View File

@ -0,0 +1,3 @@
cp.extra=${tools.jar}
javac.source=1.6
javac.compilerargs=-Xlint -Xlint:-serial

View File

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://www.netbeans.org/ns/project/1">
<type>org.netbeans.modules.apisupport.project</type>
<configuration>
<data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
<code-name-base>org.intrace.visualvm</code-name-base>
<standalone/>
<module-dependencies>
<dependency>
<code-name-base>com.sun.tools.visualvm.application</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<release-version>0-1</release-version>
<specification-version>1.2</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>com.sun.tools.visualvm.attach</code-name-base>
<run-dependency>
<release-version>0-1</release-version>
<specification-version>1.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>com.sun.tools.visualvm.core</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<release-version>0-1</release-version>
<specification-version>1.3</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>com.sun.tools.visualvm.host</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<release-version>0-1</release-version>
<specification-version>1.0</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>com.sun.tools.visualvm.tools</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<release-version>0-1</release-version>
<specification-version>1.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.modules</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.13.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.util</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.31.1.1</specification-version>
</run-dependency>
</dependency>
</module-dependencies>
<public-packages/>
</data>
</configuration>
</project>

View File

@ -0,0 +1,23 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.intrace.visualvm;
import org.intrace.visualvm.view.InTraceViewProvider;
import org.openide.modules.ModuleInstall;
/**
* Manages a module's lifecycle. Remember that an installer is optional and
* often not needed at all.
*/
public class Installer extends ModuleInstall {
@Override
public void restored() {
InTraceViewProvider.initialize();
System.out.println(Locator.agentPath);
System.out.println(Locator.winClientPath);
System.out.println(Locator.linuxClientPath);
}
}

View File

@ -0,0 +1,64 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.intrace.visualvm;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import org.openide.modules.InstalledFileLocator;
/**
*
* @author mch50
*/
public class Locator {
public static final String agentPath;
public static final URL linuxClientPath;
public static final URL winClientPath;
static {
File locatedFile = InstalledFileLocator.getDefault().locate("modules/ext/intrace-agent.jar", "com.sun.btrace", false); // NOI18N
if (locatedFile != null) {
agentPath = locatedFile.getAbsolutePath();
} else {
agentPath = null;
}
locatedFile = InstalledFileLocator.getDefault().locate("modules/ext/intrace-client-gui-win.jar", "com.sun.btrace", false); // NOI18N
if (locatedFile != null) {
URL lWinClientPath = null;
try {
lWinClientPath = locatedFile.toURI().toURL();
} catch (MalformedURLException ex) {
//
}
if (lWinClientPath != null) {
winClientPath = lWinClientPath;
} else {
winClientPath = null;
}
} else {
winClientPath = null;
}
locatedFile = InstalledFileLocator.getDefault().locate("modules/ext/intrace-client-gui-linux.jar", "com.sun.btrace", false); // NOI18N
if (locatedFile != null) {
URL lLinuxClientPath = null;
try {
lLinuxClientPath = locatedFile.toURI().toURL();
} catch (MalformedURLException ex) {
//
}
if (lLinuxClientPath != null) {
linuxClientPath = lLinuxClientPath;
} else {
linuxClientPath = null;
}
} else {
linuxClientPath = null;
}
}
}

View File

@ -0,0 +1 @@
InTraceApplicationAction.title=InTrace Application...

View File

@ -0,0 +1,43 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.intrace.visualvm.actions;
import com.sun.tools.visualvm.application.Application;
import com.sun.tools.visualvm.application.jvm.Jvm;
import com.sun.tools.visualvm.application.jvm.JvmFactory;
import com.sun.tools.visualvm.core.ui.DataSourceWindowManager;
import com.sun.tools.visualvm.core.ui.actions.SingleDataSourceAction;
import java.awt.event.ActionEvent;
import org.intrace.visualvm.impl.InTraceDataSource;
import org.openide.util.NbBundle;
/**
*
* @author mch50
*/
public class InTraceApplicationAction extends SingleDataSourceAction<Application> {
@Override
protected void actionPerformed(Application app, ActionEvent actionEvent) {
InTraceDataSource dataSource = new InTraceDataSource(app);
DataSourceWindowManager.sharedInstance().openDataSource(dataSource);
}
@Override
protected boolean isEnabled(Application app) {
Jvm jvm = JvmFactory.getJVMFor(app);
return app.isLocalApplication() && jvm.isAttachable() && jvm.isGetSystemPropertiesSupported();
}
public static synchronized InTraceApplicationAction newInstance() {
return new InTraceApplicationAction();
}
private InTraceApplicationAction() {
super(Application.class);
putValue(NAME, NbBundle.getMessage(InTraceApplicationAction.class, "InTraceApplicationAction.title")); // NOI18N
}
}

View File

@ -0,0 +1,23 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.intrace.visualvm.impl;
import com.sun.tools.visualvm.application.Application;
import com.sun.tools.visualvm.core.datasource.DataSource;
/**
*
* @author mch50
*/
public class InTraceDataSource extends DataSource {
public final Application app;
public InTraceDataSource(Application app) {
super(app);
this.app = app;
}
}

View File

@ -0,0 +1,52 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.intrace.visualvm.impl;
import com.sun.tools.attach.VirtualMachine;
import com.sun.tools.visualvm.application.Application;
import com.sun.tools.visualvm.application.jvm.Jvm;
import com.sun.tools.visualvm.application.jvm.JvmFactory;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import org.intrace.visualvm.Locator;
import org.openide.util.Exceptions;
/**
*
* @author mch50
*/
public class InTraceLoader {
public static void loadAgent(Application app) {
Jvm jvm = JvmFactory.getJVMFor(app);
if (app.isLocalApplication() && jvm.isAttachable() && jvm.isGetSystemPropertiesSupported()) {
try {
VirtualMachine vm = VirtualMachine.attach(String.valueOf(app.getPid()));
vm.loadAgent(Locator.agentPath, "");
} catch (Exception ex) {
Exceptions.printStackTrace(ex);
}
}
}
public static void launchClient() {
Runnable launchClientThread = new Runnable() {
@Override
public void run() {
URLClassLoader classLoader = new URLClassLoader(new URL[]{Locator.winClientPath});
try {
Class<?> guiClass = classLoader.loadClass("org.intrace.client.gui.TraceWindow");
Object guiObj = guiClass.newInstance();
Method guiOpen = guiClass.getMethod("open");
guiOpen.invoke(guiObj, new Object[0]);
} catch (Exception ex) {
Exceptions.printStackTrace(ex);
}
}
};
new Thread(launchClientThread).start();
}
}

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" "http://www.netbeans.org/dtds/filesystem-1_1.dtd">
<filesystem>
<folder name="VisualVM">
<folder name="ExplorerPopupSelection">
<file name="ExplorerPopupSelection-Separator-2000_1.instance" url="ExplorerPopupSelection-Separator-2000_1.instance">
<attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
<attr name="position" intvalue="2350"/>
</file>
<file name="org-intrace-visualvm-actions-InTraceApplicationAction.instance">
<attr name="instanceCreate" methodvalue="org.intrace.visualvm.actions.InTraceApplicationAction.newInstance"/>
<attr name="position" intvalue="2400"/>
</file>
</folder>
</folder>
</filesystem>

View File

@ -0,0 +1,80 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.intrace.visualvm.view;
import com.sun.tools.visualvm.core.ui.DataSourceView;
import com.sun.tools.visualvm.core.ui.components.DataViewComponent;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JPanel;
import org.intrace.visualvm.impl.InTraceLoader;
import org.intrace.visualvm.impl.InTraceDataSource;
import org.openide.util.Utilities;
/**
*
* @author mch50
*/
public class InTraceView extends DataSourceView {
private final InTraceDataSource application;
private DataViewComponent dvc;
//Reusing an image from the sources:
private static final String IMAGE_PATH = "com/sun/tools/visualvm/coredump/resources/coredump.png"; // NOI18N
public InTraceView(InTraceDataSource application) {
super(application, "InTrace", new ImageIcon(Utilities.loadImage(IMAGE_PATH, true)).getImage(), 60, false);
this.application = application;
}
@Override
protected DataViewComponent createComponent() {
//Data area for master view:
JPanel generalDataArea = new JPanel();
generalDataArea.setBorder(BorderFactory.createEmptyBorder(14, 8, 14, 8));
generalDataArea.setOpaque(false);
JButton loadAgentButton = new JButton("Load InTrace Agent");
loadAgentButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
InTraceLoader.loadAgent(application.app);
}
});
JButton launchClient = new JButton("Launch InTrace Client");
launchClient.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
InTraceLoader.launchClient();
}
});
generalDataArea.add(loadAgentButton);
generalDataArea.add(launchClient);
//Master view:
DataViewComponent.MasterView masterView = new DataViewComponent.MasterView
("InTrace", null, generalDataArea);
//Configuration of master view:
DataViewComponent.MasterViewConfiguration masterConfiguration =
new DataViewComponent.MasterViewConfiguration(false);
//Add the master view and configuration view to the component:
dvc = new DataViewComponent(masterView, masterConfiguration);
return dvc;
}
}

View File

@ -0,0 +1,39 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.intrace.visualvm.view;
import com.sun.tools.visualvm.core.ui.DataSourceView;
import com.sun.tools.visualvm.core.ui.DataSourceViewProvider;
import com.sun.tools.visualvm.core.ui.DataSourceViewsManager;
import org.intrace.visualvm.impl.InTraceDataSource;
/**
*
* @author mch50
*/
public class InTraceViewProvider extends DataSourceViewProvider<InTraceDataSource> {
private static DataSourceViewProvider<InTraceDataSource> instance = new InTraceViewProvider();
@Override
public boolean supportsViewFor(InTraceDataSource application) {
//Always shown:
return true;
}
@Override
public synchronized DataSourceView createView(final InTraceDataSource application) {
return new InTraceView(application);
}
public static void initialize() {
DataSourceViewsManager.sharedInstance().addViewProvider(instance, InTraceDataSource.class);
}
static void unregister() {
DataSourceViewsManager.sharedInstance().removeViewProvider(instance);
}
}

Binary file not shown.

View File

@ -38,7 +38,7 @@
<mkdir dir="./built/" />
<!-- CUI Agent Loader -->
<jar destfile="./built/cuiagentloader.jar" compress="false">
<jar destfile="./built/agentloader-cui.jar" compress="false">
<manifest>
<attribute name="Main-Class" value="org.intrace.agentloader.AgentLoader" />
<attribute name="Class-Path" value=". ./tools.jar" />

View File

@ -1,4 +1,4 @@
<project name="TraceAgent" basedir="." default="help">
<project name="InTrace" basedir="." default="help">
<!-- directory that contains emma.jar and emma_ant.jar: -->
<path id="emma.lib" >
@ -77,7 +77,7 @@
<mkdir dir="./build/jars/" />
<!-- Trace Agent -->
<jarjar jarfile="./build/jars/traceagent.jar" compress="false">
<jarjar jarfile="./build/jars/intrace-agent.jar" compress="false">
<manifest>
<attribute name="Premain-Class" value="org.intrace.agent.Agent" />
<attribute name="Agent-Class" value="org.intrace.agent.Agent" />
@ -93,7 +93,7 @@
</jarjar>
<!-- Test Trace Agent -->
<jar destfile="./build/jars/traceagent_test.jar" compress="false">
<jar destfile="./build/jars/intrace-agent-test.jar" compress="false">
<manifest>
<attribute name="Premain-Class" value="org.intrace.agent.Agent" />
<attribute name="Agent-Class" value="org.intrace.agent.Agent" />
@ -104,7 +104,7 @@
</jar>
<!-- CUI Trace Client -->
<jar destfile="./build/jars/cuitraceclient.jar" compress="false">
<jar destfile="./build/jars/intrace-client-cui.jar" compress="false">
<manifest>
<attribute name="Main-Class" value="org.intrace.client.cui.TraceClient" />
<attribute name="Class-Path" value="." />
@ -116,7 +116,7 @@
</jar>
<!-- GUI Trace Client - Windows -->
<jar destfile="./build/jars/guitraceclient-win.jar" filesetmanifest="mergewithoutmain">
<jar destfile="./build/jars/intrace-client-gui-win.jar" filesetmanifest="mergewithoutmain">
<manifest>
<attribute name="Main-Class" value="org.intrace.client.gui.TraceClient" />
<attribute name="Class-Path" value="." />
@ -130,7 +130,7 @@
</jar>
<!-- GUI Trace Client - Linux -->
<jar destfile="./build/jars/guitraceclient-linux.jar" filesetmanifest="mergewithoutmain">
<jar destfile="./build/jars/intrace-client-gui-linux.jar" filesetmanifest="mergewithoutmain">
<manifest>
<attribute name="Main-Class" value="org.intrace.client.gui.TraceClient" />
<attribute name="Class-Path" value="." />
@ -186,7 +186,7 @@
</classpath>
<jvmarg value="-Demma.coverage.out.file=./reports/emma/metadata/coverage.emma" />
<jvmarg value="-Demma.coverage.out.merge=true" />
<jvmarg value="-javaagent:lib/traceagent_test.jar"/>
<jvmarg value="-javaagent:lib/intrace-agent-test.jar"/>
<formatter type="xml"/>
<formatter type="plain"/>
@ -223,7 +223,7 @@
<mkdir dir="./reports/findbugs" />
<!-- Build Findbugs Trace Agent (Don't include ASM classes) -->
<jar destfile="./reports/findbugs/traceagent_findbugs.jar" compress="false">
<jar destfile="./reports/findbugs/intrace-agent-findbugs.jar" compress="false">
<fileset dir="./build/classes" includes="**/agent/**/*.class" />
<fileset dir="./build/classes" includes="**/output/**/*.class" />
<fileset dir="./build/classes" includes="**/shared/*.class" />
@ -231,14 +231,14 @@
<findbugs home="${findbugs.home}"
output="xml"
outputFile="./reports/findbugs/traceagent-fb.xml"
outputFile="./reports/findbugs/intrace-agent-findbugs-results.xml"
excludeFilter="./conf/findbugs_exclude.xml"
jvmargs="-Xmx256m">
<auxClasspath>
<fileset dir="./lib" includes="*.jar" />
</auxClasspath>
<sourcePath path="./src" />
<class location="./reports/findbugs/traceagent_findbugs.jar" />
<class location="./reports/findbugs/intrace-agent-findbugs.jar" />
</findbugs>
</target>
@ -263,7 +263,7 @@
<classpath>
<pathelement path="./build/test" />
</classpath>
<jvmarg value="-javaagent:build/jars/traceagent.jar=[instru-true" />
<jvmarg value="-javaagent:build/jars/intrace-agent.jar=[instru-true" />
</java>
</target>
@ -273,7 +273,7 @@
<classpath>
<pathelement path="./build/test" />
</classpath>
<jvmarg value="-javaagent:build/jars/traceagent.jar=[instru-true" />
<jvmarg value="-javaagent:build/jars/intrace-agent.jar=[instru-true" />
</java>
</target>

Binary file not shown.

Binary file not shown.

View File

@ -133,15 +133,12 @@ public class ClassTransformer implements ClassFileTransformer
return false;
}
// Don't modify self
if (className.startsWith("org.intrace")
|| className.contains("objectweb.asm"))
// Don't sensitive classes
if (isSensitiveClass(className))
{
if (settings.isVerboseMode())
{
System.out
.println("Ignoring class in org.intrace or objectweb.asm package: "
+ className);
System.out.println("Ignoring sensitive class: " + className);
}
return false;
}
@ -170,6 +167,8 @@ public class ClassTransformer implements ClassFileTransformer
// Don't modify a class from a JAR file unless this is allowed
CodeSource codeSource = protectionDomain.getCodeSource();
if (!settings.allowJarsToBeTraced() && (codeSource != null)
&& (codeSource.getLocation() != null)
&& (codeSource.getLocation().getPath() != null)
&& codeSource.getLocation().getPath().endsWith(".jar"))
{
if (settings.isVerboseMode())
@ -210,6 +209,14 @@ public class ClassTransformer implements ClassFileTransformer
return true;
}
private boolean isSensitiveClass(String className)
{
return className.contains("intrace") || className.contains("objectweb.asm")
|| className.startsWith("sun")
|| className.startsWith("org.openide")
|| className.startsWith("com.sun") || className.startsWith("java");
}
/**
* java.lang.instrument Entry Point
* <p>
@ -230,10 +237,7 @@ public class ClassTransformer implements ClassFileTransformer
if (isToBeConsideredForInstrumentation(classBeingRedefined, loader,
className, protectionDomain))
{
if (settings.isVerboseMode())
{
System.out.println("!! Instrumenting class: " + compclass);
}
System.out.println("!! Instrumenting class: " + compclass);
if (settings.saveTracedClassfiles())
{