mirror of https://github.com/mchr3k/org.intrace
Development work to allow any classes to be traced. This will break the tests.
This commit is contained in:
parent
580b21e77a
commit
4474c7d8ec
|
|
@ -10,7 +10,6 @@
|
|||
<classpathentry kind="lib" path="lib/asm-debug-all-3.3.jar"/>
|
||||
<classpathentry kind="lib" path="lib/jar-in-jar-loader.jar"/>
|
||||
<classpathentry kind="lib" path="lib/swt-win32-3.6.2.jar"/>
|
||||
<classpathentry kind="con" path="SWT_CONTAINER"/>
|
||||
<classpathentry kind="lib" path="lib/miglayout-3.7.3.1-swt.jar"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
|
|
|
|||
|
|
@ -76,22 +76,6 @@
|
|||
<mkdir dir="./build/tmp/" />
|
||||
<mkdir dir="./build/jars/" />
|
||||
|
||||
<!-- Test Trace Agent -->
|
||||
<if>
|
||||
<available file="./lib/intrace-agent-test.jar"/>
|
||||
<else>
|
||||
<jar destfile="./lib/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" />
|
||||
<attribute name="Can-Redefine-Classes" value="true" />
|
||||
<attribute name="Git-Revision" value="${git.revision}" />
|
||||
<attribute name="Implementation-Version" value="${git.tag}" />
|
||||
</manifest>
|
||||
</jar>
|
||||
</else>
|
||||
</if>
|
||||
|
||||
<!-- Agent -->
|
||||
<jarjar jarfile="./build/jars/intrace-agent.jar">
|
||||
<manifest>
|
||||
|
|
@ -108,16 +92,17 @@
|
|||
<zipfileset excludes="META-INF/*.MF" src="./lib/asm-debug-all-3.3.jar"/>
|
||||
<rule pattern="org.objectweb.asm.**" result="org.intrace.internal.objectweb.asm.@1"/>
|
||||
</jarjar>
|
||||
<copy file="./build/jars/intrace-agent.jar" todir="./lib/" />
|
||||
|
||||
<!-- UI (Stage 1) -->
|
||||
<jarjar jarfile="./build/tmp/intrace-ui-wrapper.jar">
|
||||
<jarjar jarfile="./build/tmp/intrace-ui-wrapper.jar">
|
||||
<fileset dir="./build/classes" includes="**/shared/*.class" />
|
||||
<fileset dir="./build/classes" includes="**/client/gui/**/*.class" />
|
||||
<zipfileset excludes="META-INF/*.MF" src="lib/miglayout-3.7.3.1-swt.jar"/>
|
||||
</jarjar>
|
||||
|
||||
|
||||
<!-- UI (Stage 2) -->
|
||||
<jarjar jarfile="./build/jars/intrace-ui.jar">
|
||||
<jarjar jarfile="./build/jars/intrace-ui.jar">
|
||||
<manifest>
|
||||
<attribute name="Main-Class" value="org.intrace.client.loader.InTraceStandaloneUILoader" />
|
||||
<attribute name="Class-Path" value="." />
|
||||
|
|
@ -127,14 +112,14 @@
|
|||
<fileset dir="./build/classes" includes="**/client/loader/*.class" />
|
||||
<fileset dir="./build/tmp" includes="intrace-ui-wrapper.jar" />
|
||||
<fileset dir="./lib" includes="swt-*.jar" />
|
||||
<zipfileset excludes="META-INF/*.MF" src="lib/jar-in-jar-loader.jar"/>
|
||||
<zipfileset excludes="META-INF/*.MF" src="lib/jar-in-jar-loader.jar"/>
|
||||
</jarjar>
|
||||
|
||||
<!-- UI Library -->
|
||||
<jar jarfile="./build/jars/intrace-ui-helper.jar">
|
||||
<jar jarfile="./build/jars/intrace-ui-helper.jar">
|
||||
<fileset dir="./build/classes" includes="**/shared/*.class" />
|
||||
<fileset dir="./build/classes" includes="**/client/gui/helper/*.class" />
|
||||
</jar>
|
||||
</jar>
|
||||
</target>
|
||||
|
||||
<target name="test" description="Run Tests" depends="build" >
|
||||
|
|
@ -184,9 +169,9 @@
|
|||
<formatter type="plain"/>
|
||||
|
||||
<batchtest fork="yes" todir="./reports/junit/raw">
|
||||
<fileset dir="./testsrc">
|
||||
<include name="**/*Test.java"/>
|
||||
</fileset>
|
||||
<fileset dir="./testsrc">
|
||||
<include name="**/*Test.java"/>
|
||||
</fileset>
|
||||
</batchtest>
|
||||
</junit>
|
||||
|
||||
|
|
@ -235,9 +220,9 @@
|
|||
|
||||
</target>
|
||||
|
||||
<target name="validate" description="Build jars and run all automated tests" depends="jar, test, findbugs" >
|
||||
<target name="validate" description="Build jars and run all automated tests" depends="jar, test, findbugs" >
|
||||
</target>
|
||||
|
||||
|
||||
<target name="release1" description="Validate InTrace and copy files ready for Eclipse build" depends="validate,update_eclipse_jars">
|
||||
<copy todir="../binaries/jars/latest_development" overwrite="true">
|
||||
<fileset file="./build/jars/intrace-agent.jar" />
|
||||
|
|
@ -249,12 +234,12 @@
|
|||
<echo>****</echo>
|
||||
<echo>****</echo>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="release2" description="Copy around built Eclipse files">
|
||||
<copy todir="../intrace.appengine/war" overwrite="true">
|
||||
<fileset dir="../intrace.ecl.site/" excludes="artifacts.jar,content.jar,.project"/>
|
||||
</copy>
|
||||
|
||||
|
||||
<delete file="../binaries/jars/latest_development/intrace.ecl.site.zip" />
|
||||
<zip destfile="../binaries/jars/latest_development/intrace.ecl.site.zip"
|
||||
basedir="../intrace.ecl.site/"
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
|
|
@ -1,14 +1,12 @@
|
|||
package org.intrace.agent;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.instrument.Instrumentation;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
import org.intrace.agent.server.AgentClientConnection;
|
||||
import org.intrace.agent.server.AgentServer;
|
||||
import org.intrace.output.AgentHelper;
|
||||
import org.intrace.output.IInstrumentationHandler;
|
||||
import org.intrace.output.trace.TraceHandler;
|
||||
|
||||
/**
|
||||
* InTrace Agent: Installs a Class Transformer to instrument class bytecode. The
|
||||
|
|
@ -39,100 +37,26 @@ public class Agent
|
|||
initialize(agentArgs, inst);
|
||||
}
|
||||
|
||||
/**
|
||||
* Common init function.
|
||||
*
|
||||
* @param agentArgs
|
||||
* @param inst
|
||||
*/
|
||||
private static void initialize(String agentArgs, Instrumentation inst)
|
||||
{
|
||||
System.out.println("## Loaded InTrace Agent.");
|
||||
|
||||
if (agentArgs == null)
|
||||
{
|
||||
agentArgs = "";
|
||||
}
|
||||
|
||||
// Setup the trace instrumentation handler
|
||||
AgentHelper.instrumentationHandler = TraceHandler.INSTANCE;
|
||||
|
||||
// Parse startup args
|
||||
AgentSettings args = new AgentSettings(agentArgs);
|
||||
AgentHelper.getResponses(null, agentArgs);
|
||||
|
||||
// Construct Transformer
|
||||
ClassTransformer t = new ClassTransformer(inst, args);
|
||||
inst.addTransformer(t, true);
|
||||
|
||||
// Ensure loaded classes are traced
|
||||
t.instrumentKlasses(t.getLoadedClassesForModification());
|
||||
|
||||
// Start Server thread
|
||||
new AgentServer(t, args.getServerPort()).start();
|
||||
|
||||
// Store server port
|
||||
waitForServerPort();
|
||||
args.setActualServerPort(serverPort);
|
||||
|
||||
// Wait for callback connection
|
||||
if (args.getCallbackPort() > -1)
|
||||
{
|
||||
System.out.println("## Establishing Callback Connection...");
|
||||
doCallbackConnection(args.getCallbackPort(), t);
|
||||
}
|
||||
|
||||
// Wait for startup
|
||||
if (args.isWaitStart())
|
||||
{
|
||||
try
|
||||
{
|
||||
System.out.println("## Program Paused");
|
||||
AgentServer.waitForStartSignal();
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int serverPort = -1;
|
||||
|
||||
public static synchronized void setServerPort(int xiServerPort)
|
||||
{
|
||||
serverPort = xiServerPort;
|
||||
Agent.class.notifyAll();
|
||||
}
|
||||
|
||||
private static synchronized void waitForServerPort()
|
||||
{
|
||||
try
|
||||
{
|
||||
Agent.class.wait();
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
// Prepare boot classpath
|
||||
String agentPath = Agent.class.getProtectionDomain().getCodeSource()
|
||||
.getLocation().getPath();
|
||||
System.out.println("Agent path: " + agentPath);
|
||||
inst.appendToBootstrapClassLoaderSearch(new JarFile(new File(agentPath)));
|
||||
|
||||
private static void doCallbackConnection(int callbackPort, ClassTransformer t)
|
||||
{
|
||||
try
|
||||
{
|
||||
Socket callback = new Socket();
|
||||
callback.connect(new InetSocketAddress("localhost", callbackPort));
|
||||
AgentClientConnection clientConnection = new AgentClientConnection(
|
||||
callback,
|
||||
t);
|
||||
AgentServer.addClientConnection(clientConnection);
|
||||
clientConnection.start(1);
|
||||
clientConnection.waitForTraceConn();
|
||||
// Class AgentInit in boot classloader
|
||||
Class<?> agentInit = Agent.class.getClassLoader().loadClass(
|
||||
"org.intrace.agent.AgentInit");
|
||||
Method initMethod = agentInit.getMethod("initialize", String.class, Instrumentation.class);
|
||||
initMethod.invoke(null, agentArgs, inst);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ex.printStackTrace();
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
package org.intrace.agent;
|
||||
|
||||
import java.lang.instrument.Instrumentation;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
|
||||
import org.intrace.agent.server.AgentClientConnection;
|
||||
import org.intrace.agent.server.AgentServer;
|
||||
import org.intrace.output.AgentHelper;
|
||||
import org.intrace.output.trace.TraceHandler;
|
||||
|
||||
public class AgentInit
|
||||
{
|
||||
|
||||
static int serverPort = -1;
|
||||
|
||||
/**
|
||||
* Common init function.
|
||||
*
|
||||
* @param agentArgs
|
||||
* @param inst
|
||||
*/
|
||||
public static void initialize(String agentArgs, Instrumentation inst)
|
||||
{
|
||||
System.out.println("## Loaded InTrace Agent.");
|
||||
|
||||
if (agentArgs == null)
|
||||
{
|
||||
agentArgs = "";
|
||||
}
|
||||
|
||||
// Setup the trace instrumentation handler
|
||||
AgentHelper.instrumentationHandler = TraceHandler.INSTANCE;
|
||||
|
||||
// Parse startup args
|
||||
AgentSettings args = new AgentSettings(agentArgs);
|
||||
AgentHelper.getResponses(null, agentArgs);
|
||||
|
||||
// Construct Transformer
|
||||
ClassTransformer t = new ClassTransformer(inst, args);
|
||||
inst.addTransformer(t, true);
|
||||
|
||||
// Ensure loaded classes are traced
|
||||
t.instrumentKlasses(t.getLoadedClassesForModification());
|
||||
|
||||
// Start Server thread
|
||||
new AgentServer(t, args.getServerPort()).start();
|
||||
|
||||
// Store server port
|
||||
waitForServerPort();
|
||||
args.setActualServerPort(serverPort);
|
||||
|
||||
// Wait for callback connection
|
||||
if (args.getCallbackPort() > -1)
|
||||
{
|
||||
System.out.println("## Establishing Callback Connection...");
|
||||
doCallbackConnection(args.getCallbackPort(), t);
|
||||
}
|
||||
|
||||
// Wait for startup
|
||||
if (args.isWaitStart())
|
||||
{
|
||||
try
|
||||
{
|
||||
System.out.println("## Program Paused");
|
||||
AgentServer.waitForStartSignal();
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static synchronized void setServerPort(int xiServerPort)
|
||||
{
|
||||
serverPort = xiServerPort;
|
||||
AgentInit.class.notifyAll();
|
||||
}
|
||||
|
||||
static synchronized void waitForServerPort()
|
||||
{
|
||||
try
|
||||
{
|
||||
AgentInit.class.wait();
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
static void doCallbackConnection(int callbackPort, ClassTransformer t)
|
||||
{
|
||||
try
|
||||
{
|
||||
Socket callback = new Socket();
|
||||
callback.connect(new InetSocketAddress("localhost", callbackPort));
|
||||
AgentClientConnection clientConnection = new AgentClientConnection(
|
||||
callback,
|
||||
t);
|
||||
AgentServer.addClientConnection(clientConnection);
|
||||
clientConnection.start(1);
|
||||
clientConnection.waitForTraceConn();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ import java.io.FileNotFoundException;
|
|||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.Thread.UncaughtExceptionHandler;
|
||||
import java.lang.instrument.ClassFileTransformer;
|
||||
import java.lang.instrument.IllegalClassFormatException;
|
||||
import java.lang.instrument.Instrumentation;
|
||||
|
|
@ -193,10 +194,10 @@ public class ClassTransformer implements ClassFileTransformer
|
|||
|
||||
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");
|
||||
return className.contains(".intrace.") || className.contains("objectweb.asm");
|
||||
// || className.startsWith("sun")
|
||||
// || className.startsWith("org.openide")
|
||||
// || className.startsWith("com.sun") || className.startsWith("java");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -213,63 +214,87 @@ public class ClassTransformer implements ClassFileTransformer
|
|||
byte[] originalClassfile)
|
||||
throws IllegalClassFormatException
|
||||
{
|
||||
String className = internalClassName.replace('/', '.');
|
||||
ComparableClassName compclass = new ComparableClassName(className, loader);
|
||||
int modifiedSize = modifiedClasses.size();
|
||||
int allClassesSize = allClasses.size();
|
||||
|
||||
if (isToBeConsideredForInstrumentation(classBeingRedefined, loader,
|
||||
className, protectionDomain))
|
||||
// Touching the Thread and UncaughtExceptionHandler classes here is safe
|
||||
// as they must already be loaded by the time we get here.
|
||||
Thread currentTh = Thread.currentThread();
|
||||
UncaughtExceptionHandler handler = currentTh.getUncaughtExceptionHandler();
|
||||
if (handler != CRITICAL_BLOCK)
|
||||
{
|
||||
System.out.println("!! Instrumenting class: " + compclass);
|
||||
|
||||
if (settings.saveTracedClassfiles())
|
||||
{
|
||||
writeClassBytes(originalClassfile, internalClassName + "_src.class");
|
||||
}
|
||||
|
||||
byte[] newBytes;
|
||||
// Allow instrumentation to proceed
|
||||
currentTh.setUncaughtExceptionHandler(CRITICAL_BLOCK);
|
||||
|
||||
try
|
||||
{
|
||||
newBytes = getInstrumentedClassBytes(className, originalClassfile);
|
||||
String className = internalClassName.replace('/', '.');
|
||||
ComparableClassName compclass = new ComparableClassName(className, loader);
|
||||
System.out.println("!! Consider: " + compclass);
|
||||
int modifiedSize = modifiedClasses.size();
|
||||
int allClassesSize = allClasses.size();
|
||||
|
||||
if (isToBeConsideredForInstrumentation(classBeingRedefined, loader,
|
||||
className, protectionDomain))
|
||||
{
|
||||
System.out.println("!! Instrumenting class: " + compclass);
|
||||
|
||||
if (settings.saveTracedClassfiles())
|
||||
{
|
||||
writeClassBytes(originalClassfile, internalClassName + "_src.class");
|
||||
}
|
||||
|
||||
byte[] newBytes;
|
||||
try
|
||||
{
|
||||
newBytes = getInstrumentedClassBytes(className, originalClassfile);
|
||||
}
|
||||
catch (RuntimeException th)
|
||||
{
|
||||
// Ensure the JVM doesn't silently swallow an unchecked exception
|
||||
th.printStackTrace();
|
||||
throw th;
|
||||
}
|
||||
catch (Error th)
|
||||
{
|
||||
// Ensure the JVM doesn't silently swallow an unchecked exception
|
||||
th.printStackTrace();
|
||||
throw th;
|
||||
}
|
||||
|
||||
if (settings.saveTracedClassfiles())
|
||||
{
|
||||
writeClassBytes(newBytes, internalClassName + "_gen.class");
|
||||
}
|
||||
|
||||
modifiedClasses.add(compclass);
|
||||
|
||||
if (!isSensitiveClass(className))
|
||||
{
|
||||
// Only send updates if we aren't handling a "sensitive class"
|
||||
detectStatusUpdate(modifiedSize, allClassesSize);
|
||||
}
|
||||
|
||||
return newBytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
modifiedClasses.remove(compclass);
|
||||
|
||||
if (!isSensitiveClass(className))
|
||||
{
|
||||
// Only send updates if we aren't handling a "sensitive class"
|
||||
detectStatusUpdate(modifiedSize, allClassesSize);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch (RuntimeException th)
|
||||
finally
|
||||
{
|
||||
// Ensure the JVM doesn't silently swallow an unchecked exception
|
||||
th.printStackTrace();
|
||||
throw th;
|
||||
currentTh.setUncaughtExceptionHandler(handler);
|
||||
}
|
||||
catch (Error th)
|
||||
{
|
||||
// Ensure the JVM doesn't silently swallow an unchecked exception
|
||||
th.printStackTrace();
|
||||
throw th;
|
||||
}
|
||||
|
||||
if (settings.saveTracedClassfiles())
|
||||
{
|
||||
writeClassBytes(newBytes, internalClassName + "_gen.class");
|
||||
}
|
||||
|
||||
modifiedClasses.add(compclass);
|
||||
|
||||
if (!isSensitiveClass(className))
|
||||
{
|
||||
// Only send updates if we aren't handling a "sensitive class"
|
||||
detectStatusUpdate(modifiedSize, allClassesSize);
|
||||
}
|
||||
|
||||
return newBytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
modifiedClasses.remove(compclass);
|
||||
|
||||
if (!isSensitiveClass(className))
|
||||
{
|
||||
// Only send updates if we aren't handling a "sensitive class"
|
||||
detectStatusUpdate(modifiedSize, allClassesSize);
|
||||
}
|
||||
// This thread is currently handling instrumenting a class.
|
||||
// We must return now.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -501,39 +526,80 @@ public class ClassTransformer implements ClassFileTransformer
|
|||
return unmodifiedKlasses;
|
||||
}
|
||||
|
||||
public void instrumentKlasses(Set<ComparableClass> klasses)
|
||||
{
|
||||
try
|
||||
{
|
||||
bulkUpdateActive.set(true);
|
||||
int countNumClasses = 0;
|
||||
int totalNumClasses = klasses.size();
|
||||
broadcastProgress(countNumClasses, totalNumClasses);
|
||||
for (ComparableClass klass : klasses)
|
||||
{
|
||||
try
|
||||
{
|
||||
inst.retransformClasses(klass.klass);
|
||||
private InstruKlassesAction instruAction = null;
|
||||
private final Object instruLock = new Object();
|
||||
|
||||
countNumClasses++;
|
||||
if ((countNumClasses % 10) == 0)
|
||||
public void instrumentKlasses(final Set<ComparableClass> klasses)
|
||||
{
|
||||
synchronized (instruLock)
|
||||
{
|
||||
if (instruAction != null)
|
||||
{
|
||||
instruAction.active = false;
|
||||
instruAction = null;
|
||||
}
|
||||
instruAction = new InstruKlassesAction(klasses);
|
||||
instruAction.start();
|
||||
}
|
||||
}
|
||||
|
||||
private class InstruKlassesAction implements Runnable
|
||||
{
|
||||
public InstruKlassesAction(Set<ComparableClass> klasses)
|
||||
{
|
||||
this.klasses = klasses;
|
||||
}
|
||||
|
||||
private final Set<ComparableClass> klasses;
|
||||
public volatile boolean active = true;
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
bulkUpdateActive.set(true);
|
||||
int countNumClasses = 0;
|
||||
int totalNumClasses = klasses.size();
|
||||
broadcastProgress(countNumClasses, totalNumClasses);
|
||||
for (ComparableClass klass : klasses)
|
||||
{
|
||||
if (!active)
|
||||
{
|
||||
broadcastProgress(countNumClasses, totalNumClasses);
|
||||
break;
|
||||
}
|
||||
try
|
||||
{
|
||||
inst.retransformClasses(klass.klass);
|
||||
|
||||
countNumClasses++;
|
||||
if ((countNumClasses % 10) == 0)
|
||||
{
|
||||
broadcastProgress(countNumClasses, totalNumClasses);
|
||||
}
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
// Write exception to stdout
|
||||
System.out.println(klass.klass.getName());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
// Write exception to stdout
|
||||
System.out.println(klass.klass.getName());
|
||||
e.printStackTrace();
|
||||
}
|
||||
broadcastProgress(totalNumClasses, totalNumClasses, true);
|
||||
}
|
||||
broadcastProgress(totalNumClasses, totalNumClasses, true);
|
||||
finally
|
||||
{
|
||||
bulkUpdateActive.set(false);
|
||||
broadcastStatus(modifiedClasses.size(), allClasses.size());
|
||||
}
|
||||
}
|
||||
finally
|
||||
|
||||
public void start()
|
||||
{
|
||||
bulkUpdateActive.set(false);
|
||||
broadcastStatus(modifiedClasses.size(), allClasses.size());
|
||||
Thread th = new Thread(this);
|
||||
th.setName("instrumentKlasses");
|
||||
th.setDaemon(true);
|
||||
th.start();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -804,4 +870,13 @@ public class ClassTransformer implements ClassFileTransformer
|
|||
return klassloaderStr + klass.getName();
|
||||
}
|
||||
}
|
||||
public static final CriticalBlock CRITICAL_BLOCK = new CriticalBlock();
|
||||
private static class CriticalBlock implements Thread.UncaughtExceptionHandler
|
||||
{
|
||||
@Override
|
||||
public void uncaughtException(Thread t, Throwable e)
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import java.io.InputStream;
|
|||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.Thread.UncaughtExceptionHandler;
|
||||
import java.net.Socket;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
|
@ -83,63 +84,72 @@ public class AgentClientConnection implements Runnable
|
|||
@Override
|
||||
public void run()
|
||||
{
|
||||
UncaughtExceptionHandler handler = Thread.currentThread().getUncaughtExceptionHandler();
|
||||
try
|
||||
{
|
||||
Thread.currentThread().setUncaughtExceptionHandler(ClassTransformer.CRITICAL_BLOCK);
|
||||
try
|
||||
{
|
||||
while (true)
|
||||
try
|
||||
{
|
||||
String message = receiveMessage();
|
||||
if (message.equals("getsettings"))
|
||||
while (true)
|
||||
{
|
||||
Map<String, String> settingsMap = new HashMap<String, String>();
|
||||
settingsMap.putAll(transformer.getSettings());
|
||||
settingsMap.putAll(AgentHelper.getSettings());
|
||||
AgentServer.broadcastMessage(this, settingsMap);
|
||||
}
|
||||
else if (message.equals("help"))
|
||||
{
|
||||
Set<String> commandSet = new HashSet<String>();
|
||||
commandSet.addAll(AgentConfigConstants.COMMANDS);
|
||||
commandSet.addAll(TraceConfigConstants.COMMANDS);
|
||||
sendMessage(commandSet);
|
||||
}
|
||||
else if (message.equalsIgnoreCase(AgentConfigConstants.START_ACTIVATE))
|
||||
{
|
||||
transformer.getResponse(this, message);
|
||||
AgentServer.setStartSignalled();
|
||||
}
|
||||
else
|
||||
{
|
||||
List<String> responses = transformer.getResponse(this, message);
|
||||
if (responses.size() > 0)
|
||||
String message = receiveMessage();
|
||||
if (message.equals("getsettings"))
|
||||
{
|
||||
for (String response : responses)
|
||||
{
|
||||
sendMessage(response);
|
||||
}
|
||||
Map<String, String> settingsMap = new HashMap<String, String>();
|
||||
settingsMap.putAll(transformer.getSettings());
|
||||
settingsMap.putAll(AgentHelper.getSettings());
|
||||
AgentServer.broadcastMessage(this, settingsMap);
|
||||
}
|
||||
else if (message.equals("help"))
|
||||
{
|
||||
Set<String> commandSet = new HashSet<String>();
|
||||
commandSet.addAll(AgentConfigConstants.COMMANDS);
|
||||
commandSet.addAll(TraceConfigConstants.COMMANDS);
|
||||
sendMessage(commandSet);
|
||||
}
|
||||
else if (message.equalsIgnoreCase(AgentConfigConstants.START_ACTIVATE))
|
||||
{
|
||||
transformer.getResponse(this, message);
|
||||
AgentServer.setStartSignalled();
|
||||
}
|
||||
else
|
||||
{
|
||||
sendMessage("OK");
|
||||
List<String> responses = transformer.getResponse(this, message);
|
||||
if (responses.size() > 0)
|
||||
{
|
||||
for (String response : responses)
|
||||
{
|
||||
sendMessage(response);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sendMessage("OK");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
System.out.println("## Control Connection Disconnected (Port: " +
|
||||
connectedClient.getPort() + ")");
|
||||
}
|
||||
connectedClient.close();
|
||||
}
|
||||
catch (IOException ex)
|
||||
catch (IOException e1)
|
||||
{
|
||||
System.out.println("## Control Connection Disconnected (Port: " +
|
||||
connectedClient.getPort() + ")");
|
||||
e1.printStackTrace();
|
||||
}
|
||||
finally
|
||||
{
|
||||
AgentServer.removeClientConnection(this);
|
||||
}
|
||||
connectedClient.close();
|
||||
}
|
||||
catch (IOException e1)
|
||||
{
|
||||
e1.printStackTrace();
|
||||
}
|
||||
finally
|
||||
{
|
||||
AgentServer.removeClientConnection(this);
|
||||
Thread.currentThread().setUncaughtExceptionHandler(handler);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -170,9 +180,9 @@ public class AgentClientConnection implements Runnable
|
|||
* @param xiObject
|
||||
* @throws IOException
|
||||
*/
|
||||
public void sendMessage(Object xiObject) throws IOException
|
||||
public synchronized void sendMessage(Object xiObject) throws IOException
|
||||
{
|
||||
synchronized (connectedClient)
|
||||
// synchronized (connectedClient)
|
||||
{
|
||||
OutputStream out = connectedClient.getOutputStream();
|
||||
ObjectOutputStream objOut = new ObjectOutputStream(out);
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import java.net.Socket;
|
|||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.intrace.agent.Agent;
|
||||
import org.intrace.agent.AgentInit;
|
||||
import org.intrace.agent.ClassTransformer;
|
||||
|
||||
/**
|
||||
|
|
@ -129,7 +129,7 @@ public class AgentServer implements Runnable
|
|||
System.out.println("## Listening on port " + serversock.getLocalPort());
|
||||
System.setProperty("org.intrace.port",
|
||||
Integer.toString(serversock.getLocalPort()));
|
||||
Agent.setServerPort(serversock.getLocalPort());
|
||||
AgentInit.setServerPort(serversock.getLocalPort());
|
||||
while (true)
|
||||
{
|
||||
Socket connectedClient = serversock.accept();
|
||||
|
|
|
|||
Loading…
Reference in New Issue