mirror of https://github.com/mchr3k/org.intrace
interface support now turned off by default for stability reasons, esp. on larger projects.
This commit is contained in:
parent
831929f4dd
commit
8f8bdaa5ee
|
|
@ -423,6 +423,14 @@
|
|||
<jvmarg value="-javaagent:build/jars/intrace-agent.jar=[instru-true" />
|
||||
</java>
|
||||
</target>
|
||||
<target name="example3" depends="jar,example_build">
|
||||
<java classname="example.InstrumentMeLaunch" fork="true">
|
||||
<classpath>
|
||||
<pathelement path="./build/test" />
|
||||
</classpath>
|
||||
<jvmarg value="-javaagent:build/jars/intrace-agent.jar=[instru-true" />
|
||||
</java>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="waitexample" depends="jar,example_build">
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ private InstrCriteria classesToExclude = null;
|
|||
private boolean instruEnabled = true;
|
||||
private boolean saveTracedClassfiles = false;
|
||||
private boolean verboseMode = false;
|
||||
private boolean _instrumentImplementors = false;
|
||||
|
||||
|
||||
|
||||
|
|
@ -54,6 +55,7 @@ private InstrCriteria classesToExclude = null;
|
|||
instruEnabled = oldInstance.isInstrumentationEnabled();
|
||||
saveTracedClassfiles = oldInstance.saveTracedClassfiles();
|
||||
verboseMode = oldInstance.isVerboseMode();
|
||||
_instrumentImplementors = oldInstance.instrumentImplementors();
|
||||
}
|
||||
public AgentSettings(String args)
|
||||
{
|
||||
|
|
@ -138,8 +140,17 @@ public void parseArgs(String args)
|
|||
this.classesToExclude = new InstrCriteria(classExcludeRegexStr);
|
||||
this.classesToExclude.verboseLogger = this;
|
||||
}
|
||||
else if (arg.toLowerCase(Locale.ROOT).equals(
|
||||
AgentConfigConstants.INSTRUMENT_IMPLEMENTORS
|
||||
+ "true"))
|
||||
{
|
||||
this._instrumentImplementors = true;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean instrumentImplementors() {
|
||||
return _instrumentImplementors;
|
||||
}
|
||||
public boolean isWaitStart()
|
||||
{
|
||||
return waitStart;
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentSkipListSet;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.intrace.agent.server.AgentClientConnection;
|
||||
import org.intrace.agent.server.AgentServer;
|
||||
|
|
@ -51,11 +52,21 @@ public class ClassTransformer implements ClassFileTransformer
|
|||
* Set of modified class names
|
||||
*/
|
||||
private final Set<ComparableClassName> modifiedClasses = new ConcurrentSkipListSet<ComparableClassName>();
|
||||
/**
|
||||
* Javadoc and stacktraces show that ConcurrentSkipListSet.size() takes up large amount of time.
|
||||
* This variable will be used to store count.
|
||||
*/
|
||||
private final AtomicInteger modifiedClassesCount = new AtomicInteger();
|
||||
|
||||
/**
|
||||
* Map of all seen class names
|
||||
*/
|
||||
private final Set<ComparableClassName> allClasses = new ConcurrentSkipListSet<ComparableClassName>();
|
||||
/**
|
||||
* Javadoc and stacktraces show that ConcurrentSkipListSet.size() takes up large amount of time.
|
||||
* This variable will be used to store count.
|
||||
*/
|
||||
private final AtomicInteger allClassesCount = new AtomicInteger();
|
||||
|
||||
/**
|
||||
* Instrumentation interface.
|
||||
|
|
@ -90,6 +101,8 @@ public class ClassTransformer implements ClassFileTransformer
|
|||
{
|
||||
TraceHandler.INSTANCE.writeTraceOutput("DEBUG: " + settings.toString());
|
||||
}
|
||||
this.allClassesCount.set(0);
|
||||
this.modifiedClassesCount.set(0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -110,6 +123,7 @@ public class ClassTransformer implements ClassFileTransformer
|
|||
ClassAnalysis analysis = new ClassAnalysis();
|
||||
cr.accept(analysis, 0);
|
||||
|
||||
//System.out.println("getInstrumentedClassBytes [" + xiClassName + "]");
|
||||
InstrumentedClassWriter writer = new InstrumentedClassWriter(xiClassName,
|
||||
cr, analysis,
|
||||
shouldInstrument,
|
||||
|
|
@ -152,11 +166,13 @@ public class ClassTransformer implements ClassFileTransformer
|
|||
ProtectionDomain protectionDomain,
|
||||
byte[] originalClassfile)
|
||||
{
|
||||
// System.out.println("itbcfi [" + className + "] klass [" + klass.getName() + "] protectionDomain [" + protectionDomain + "]");
|
||||
ComparableClassName compklass = new ComparableClassName(className,
|
||||
klassloader);
|
||||
|
||||
// Record all class names which get this far
|
||||
allClasses.add(compklass);
|
||||
allClassesCount.incrementAndGet();
|
||||
|
||||
// Don't modify anything if tracing is disabled
|
||||
if (!settings.isInstrumentationEnabled())
|
||||
|
|
@ -201,13 +217,15 @@ public class ClassTransformer implements ClassFileTransformer
|
|||
{
|
||||
// Actually we should modify if any of the interfaces match the regex
|
||||
boolean matchedInterface = false;
|
||||
for(String klassInterface : getInterfaces(className, originalClassfile))
|
||||
{
|
||||
if ((settings.getClassRegex() != null)
|
||||
&& matches(settings.getClassRegex(), klassInterface))
|
||||
{
|
||||
matchedInterface |= true;
|
||||
}
|
||||
if (originalClassfile !=null && settings.instrumentImplementors() ) {
|
||||
for(String klassInterface : getInterfaces(className, originalClassfile))
|
||||
{
|
||||
if ((settings.getClassRegex() != null)
|
||||
&& matches(settings.getClassRegex(), klassInterface))
|
||||
{
|
||||
matchedInterface |= true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!matchedInterface)
|
||||
|
|
@ -300,8 +318,8 @@ public class ClassTransformer implements ClassFileTransformer
|
|||
{
|
||||
String className = internalClassName.replace('/', '.');
|
||||
ComparableClassName compclass = new ComparableClassName(className, loader);
|
||||
int modifiedSize = modifiedClasses.size();
|
||||
int allClassesSize = allClasses.size();
|
||||
int modifiedSize = modifiedClassesCount.get();
|
||||
int allClassesSize = allClassesCount.get();
|
||||
|
||||
boolean shouldInstrument = isToBeConsideredForInstrumentation(classBeingRedefined, loader,
|
||||
className, protectionDomain,
|
||||
|
|
@ -342,6 +360,7 @@ public class ClassTransformer implements ClassFileTransformer
|
|||
}
|
||||
|
||||
modifiedClasses.add(compclass);
|
||||
modifiedClassesCount.getAndIncrement();
|
||||
|
||||
sendStatusUpdate(modifiedSize, allClassesSize);
|
||||
|
||||
|
|
@ -350,6 +369,7 @@ public class ClassTransformer implements ClassFileTransformer
|
|||
else
|
||||
{
|
||||
modifiedClasses.remove(compclass);
|
||||
modifiedClassesCount.decrementAndGet();
|
||||
|
||||
sendStatusUpdate(modifiedSize, allClassesSize);
|
||||
return null;
|
||||
|
|
@ -409,13 +429,13 @@ public class ClassTransformer implements ClassFileTransformer
|
|||
try
|
||||
{
|
||||
StatusUpdate update = statusHolder.getStatus();
|
||||
int newModifiedSize = modifiedClasses.size();
|
||||
int newAllClassesSize = allClasses.size();
|
||||
int newModifiedSize = modifiedClassesCount.get();
|
||||
int newAllClassesSize = allClassesCount.get();
|
||||
if (!bulkUpdateActive.get() &&
|
||||
((newModifiedSize != update.modifiedSize) ||
|
||||
(newAllClassesSize != update.allClassesSize)))
|
||||
{
|
||||
broadcastStatus(modifiedClasses.size(), allClasses.size());
|
||||
broadcastStatus(modifiedClassesCount.get(), allClassesCount.get());
|
||||
}
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
|
|
@ -524,9 +544,9 @@ public class ClassTransformer implements ClassFileTransformer
|
|||
{
|
||||
Map<String, String> settingsMap = settings.getSettingsMap();
|
||||
settingsMap.put(AgentConfigConstants.STCLS,
|
||||
Integer.toString(allClasses.size()));
|
||||
Integer.toString(allClassesCount.get()));
|
||||
settingsMap.put(AgentConfigConstants.STINST,
|
||||
Integer.toString(modifiedClasses.size()));
|
||||
Integer.toString(modifiedClassesCount.get()));
|
||||
return settingsMap;
|
||||
}
|
||||
|
||||
|
|
@ -551,12 +571,12 @@ public class ClassTransformer implements ClassFileTransformer
|
|||
else if (oldSettings.isInstrumentationEnabled() != settings
|
||||
.isInstrumentationEnabled())
|
||||
{
|
||||
// System.out.println("## Settings Changed");
|
||||
//System.out.println("## Settings Changed");
|
||||
setInstrumentationEnabled(settings.isInstrumentationEnabled());
|
||||
}
|
||||
else if (!Arrays.equals(oldSettings.getClassRegex(), settings.getClassRegex()))
|
||||
{
|
||||
// System.out.println("## Settings Changed");
|
||||
//System.out.println("## Settings Changed");
|
||||
Set<ComparableClass> klasses = new HashSet<ComparableClass>(getModifiedClasses());
|
||||
modifiedClasses.clear();
|
||||
klasses.addAll(getLoadedClassesForModification());
|
||||
|
|
@ -564,7 +584,7 @@ public class ClassTransformer implements ClassFileTransformer
|
|||
}
|
||||
else if (!Arrays.equals(oldSettings.getExcludeClassRegex(), settings.getExcludeClassRegex()))
|
||||
{
|
||||
// System.out.println("## Settings Changed");
|
||||
//System.out.println("## Settings Changed");
|
||||
Set<ComparableClass> klasses = new HashSet<ComparableClass>(getModifiedClasses());
|
||||
modifiedClasses.clear();
|
||||
klasses.addAll(getLoadedClassesForModification());
|
||||
|
|
@ -573,7 +593,7 @@ public class ClassTransformer implements ClassFileTransformer
|
|||
else if (oldSettings.saveTracedClassfiles() != settings
|
||||
.saveTracedClassfiles())
|
||||
{
|
||||
// System.out.println("## Settings Changed");
|
||||
//System.out.println("## Settings Changed");
|
||||
Set<ComparableClass> klasses = getModifiedClasses();
|
||||
modifiedClasses.clear();
|
||||
klasses.addAll(getLoadedClassesForModification());
|
||||
|
|
@ -656,7 +676,12 @@ public class ClassTransformer implements ClassFileTransformer
|
|||
+ loadedClass.getCanonicalName());
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (settings.instrumentImplementors() || isToBeConsideredForInstrumentation(
|
||||
loadedClass,
|
||||
loadedClass.getClassLoader(),
|
||||
loadedClass.getName(),
|
||||
loadedClass.getProtectionDomain(),
|
||||
null ))
|
||||
{
|
||||
ComparableClass loadedKlass = new ComparableClass(loadedClass);
|
||||
unmodifiedKlasses.add(loadedKlass);
|
||||
|
|
@ -665,6 +690,18 @@ public class ClassTransformer implements ClassFileTransformer
|
|||
return unmodifiedKlasses;
|
||||
}
|
||||
|
||||
/*
|
||||
The catch block in this method should have caught the following, but it did not.
|
||||
Need to figure out why.
|
||||
<pre>
|
||||
[java] java.lang.VerifyError
|
||||
[java] at sun.instrument.InstrumentationImpl.retransformClasses0(Native Method)
|
||||
[java] at sun.instrument.InstrumentationImpl.retransformClasses(InstrumentationImpl.java:144)
|
||||
[java] at org.intrace.agent.ClassTransformer.instrumentKlasses(ClassTransformer.java:719)
|
||||
[java] at org.intrace.agent.ClassTransformer.getResponse(ClassTransformer.java:584)
|
||||
[java] at org.intrace.agent.server.AgentClientConnection.runMethod(AgentClientConnection.java:118)
|
||||
</pre>
|
||||
*/
|
||||
public void instrumentKlasses(Set<ComparableClass> klasses)
|
||||
{
|
||||
if (!inst.isRetransformClassesSupported())
|
||||
|
|
@ -692,10 +729,10 @@ public class ClassTransformer implements ClassFileTransformer
|
|||
inst.retransformClasses(klass.klass);
|
||||
|
||||
countNumClasses++;
|
||||
if ((countNumClasses % 100) == 0)
|
||||
{
|
||||
// if ((countNumClasses % 100) == 0)
|
||||
// {
|
||||
broadcastProgress(countNumClasses, totalNumClasses);
|
||||
}
|
||||
// }
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
|
|
@ -711,7 +748,7 @@ public class ClassTransformer implements ClassFileTransformer
|
|||
finally
|
||||
{
|
||||
bulkUpdateActive.set(false);
|
||||
broadcastStatus(modifiedClasses.size(), allClasses.size());
|
||||
broadcastStatus(modifiedClasses.size(), allClassesCount.get());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@ public class InstrumentedClassWriter extends ClassWriter
|
|||
sb.append(InstrCriteria.CLASS_METHOD_DELIMITER);
|
||||
sb.append(name);
|
||||
sb.append(desc);
|
||||
//System.out.println("@#%:" + sb.toString() );
|
||||
TraceHandler.INSTANCE.writeTraceOutput("DEBUG: method signature: " + sb.toString());
|
||||
}
|
||||
MethodVisitor mv = super.visitMethod(access, name, desc, signature,
|
||||
|
|
|
|||
|
|
@ -472,7 +472,7 @@ private static final Object STACK_ELE_DELIM = ",";
|
|||
+ "]:" + xiOutput;
|
||||
// if (AgentHelper.getOutputSettings().isStdoutOutputEnabled())
|
||||
// {
|
||||
//// System.out.println(traceString);
|
||||
// System.out.println(traceString);
|
||||
// }
|
||||
|
||||
if (AgentHelper.getOutputSettings().isFileOutputEnabled())
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ public class AgentConfigConstants
|
|||
public static final String OPT_SERVER_PORT = "[serverport-";
|
||||
public static final String CALLBACK_PORT = "[callbackport-";
|
||||
public static final String EXIT_STACK_TRACE = "[exit-stack-trace-";
|
||||
public static final String INSTRUMENT_IMPLEMENTORS = "[instrument-implementors";
|
||||
|
||||
public static final String START_WAIT = "[startwait";
|
||||
public static final String START_ACTIVATE = "[startactivate";
|
||||
|
|
@ -39,5 +40,6 @@ public class AgentConfigConstants
|
|||
COMMANDS.add(OPT_SERVER_PORT + "<int>");
|
||||
COMMANDS.add(CALLBACK_PORT + "<int>");
|
||||
COMMANDS.add(EXIT_STACK_TRACE + "<true/false>");
|
||||
COMMANDS.add(INSTRUMENT_IMPLEMENTORS + "<true/false>");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
package example;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class InstrumentMe implements Runnable
|
||||
{
|
||||
private byte myField = 1;
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
byteArg((byte) 0);
|
||||
}
|
||||
|
||||
private void byteArg(byte arg)
|
||||
{
|
||||
this.myField = arg;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
package example;
|
||||
|
||||
public class InstrumentMeLaunch
|
||||
{
|
||||
public static void main(String args[]) throws Exception {
|
||||
System.out.println("Currently running sample code in background thread.");
|
||||
System.out.println("Make sure this program has -javaagent:./path/to/intrace-agent.jar on its command line.");
|
||||
System.out.println("Start InTrace GUI, download-able at https://mchr3k.github.io/org.intrace/");
|
||||
System.out.println("'Connect' & then configure GUI to trace any of these patterns:\n\n");
|
||||
System.out.println("example.InstrumentMe -- to trace all methods in class example.InstrumentMe");
|
||||
System.out.println("example.InstrumentMe -- to trace all methods in class example.InstrumentMeLaunch");
|
||||
System.out.println("example.InstrumentMe#<init>()V -- to trace this single method.");
|
||||
System.out.println("example.InstrumentMe#run()V -- to trace this single method.");
|
||||
System.out.println("example.InstrumentMe#byteArg(B)V -- to trace this single method.");
|
||||
System.out.println("example.InstrumentMeLaunch#<init>()V -- to trace this single method.");
|
||||
System.out.println("example.InstrumentMeLaunch#main([Ljava/lang/String;)V -- to trace this single method.\n\n");
|
||||
|
||||
System.out.println("Press Ctrl+C to quit this program.");
|
||||
Runnable r = new InstrumentMe();
|
||||
while(true) {
|
||||
System.out.println("About to start thread.");
|
||||
new Thread(r).start();
|
||||
Thread.sleep(2000);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -64,6 +64,25 @@ public class AgentSettingsTest extends TestCase
|
|||
assertEquals(settingsMap.get(AgentConfigConstants.VERBOSE_MODE), "true");
|
||||
}
|
||||
|
||||
public void testInstrumentImplementorsSetting() {
|
||||
AgentSettings as1 = new AgentSettings(
|
||||
AgentConfigConstants.INSTRUMENT_IMPLEMENTORS
|
||||
+ "true"
|
||||
);
|
||||
assertTrue( "unable to recognize parameter that instruments implementors of interfaces", as1.instrumentImplementors() );
|
||||
|
||||
AgentSettings as2 = new AgentSettings(
|
||||
AgentConfigConstants.INSTRUMENT_IMPLEMENTORS
|
||||
+ "false"
|
||||
);
|
||||
assertFalse( "unable to recognize parameter that instruments implementors of interfaces",as2.instrumentImplementors() );
|
||||
|
||||
AgentSettings as3 = new AgentSettings("");
|
||||
assertFalse( "unable to recognize parameter that instruments implementors of interfaces", as3.instrumentImplementors() );
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void testInstrCriteria() {
|
||||
InstrCriteria ic = new InstrCriteria("foo|bar");
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue