Open eostermueller opened 11 years ago
I took a first stab at implementing this and it didn't go too well.
In ClassTransformer.java, I used this:
private boolean matches(String[] strs, String target)
{
for (String str : strs)
{
if (str.equals(MATCH_NONE))
{
continue;
}
else if (str.equals(MATCH_ALL) ||
target.contains(str))
{
return true;
}
else if (isAssignableFrom(str, target))
{
return true;
}
}
return false;
}
private boolean isAssignableFrom(String candidateInterface, String candidateImpl) {
TraceHandler.INSTANCE.writeTraceOutput("DEBUG: Is impl class [" + candidateImpl + "] assignable from interface [" + candidateInterface + "]");
System.out.println("XX DEBUG: Is impl class [" + candidateImpl + "] assignable from interface [" + candidateInterface + "]");
boolean rc = false;
Class klazCandidateInterface = null;
Class klazCandidateImpl = null;
try {
klazCandidateInterface = Class.forName(candidateInterface);
klazCandidateImpl = Class.forName(candidateImpl);
if (klazCandidateInterface.isInterface() &&
klazCandidateInterface.isAssignableFrom(klazCandidateImpl))
{
TraceHandler.INSTANCE.writeTraceOutput("DEBUG: isAssignableFrom=true");
return true;
}
} catch (Exception e)
{ //any exception from above means the imple does not implement the interface.
if ( e.getMessage().indexOf("TraceInterface")>0) {
e.printStackTrace();
}
System.out.println("exception [" + e.getMessage() + "]");
}
TraceHandler.INSTANCE.writeTraceOutput("DEBUG: isAssignableFrom=false");
System.out.println("DEBUG: isAssignableFrom=false");
return false;
}
Can't remember exactly what the problem was, but the code just seems wrong. Before a class is loaded, this class is evaluating whether it implements an interface. But it seems like the Java API must first load a class before you can make this determination.
So, I wonder if we should consider using this ASM-based library to determine if a class implements a particular interface: * http://software.clapper.org/javautil/ * http://software.clapper.org/javautil/api/org/clapper/util/classutil/ClassFinder.html
Would appreciate any thoughts on this. --Erik
I have pushed a commit with a quick implementation of this issue.
Martin, thanks. I gave that code a try and I needed a single line of code to get it to work. Would you give it a try, and commit if it looks good? Thanks, --Erik
From org/intrace/agent/ClassTransformer.java, the method isToBeConsideredForInstrumentation().
// Don't modify classes which fail to match the regex
if ((settings.getClassRegex() == null)
|| !matches(settings.getClassRegex(), className))
{
// Actually we should modify if any of the interfaces match the regex
boolean matchedInterface = false;
for(String klassInterface : getInterfaces(className, originalClassfile))
{
/**
* ## ## ## ## ## ## ## ##
* I had to add this next line of code to get this work work.
* ## ## ## ## ## ## ## ##
*/
klassInterface = klassInterface.replace('/','.');
System.out.println("#@# Comparing [" + klassInterface + "]");
if ((settings.getClassRegex() != null)
&& matches(settings.getClassRegex(), klassInterface))
{
System.out.println("matched interface successfully!");
matchedInterface |= true;
}
}
Vendors who make tools rely in java interfaces. WebServers servers like tomcat rely on interfaces in the package javax.servlet.http. Performance monitoring tools rely on javax.sql, javax.jms and many others.
If vendors could instrument the interfaces, they could use InTrace to track method invocations, regardless of the implementation. For example, they could instrument java.sql.PreparedStatement, and get notified of method invocation events regardless of which JDBC driver was in use.
This would be invaluable for comparing functionality and performance of various implementations of any spec/interface.
Details: Enable user to click on the "Classes" button in the InTrace UI and enter the name of an interface. InTrace agent would "instrument" all classes (and subclasses and subinterfaces) that implemented the given interface.