Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

enhancement request: instrument all implementation of a given interface #31

Open
eostermueller opened this issue Sep 11, 2013 · 3 comments

Comments

@eostermueller
Copy link
Contributor

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.

@eostermueller
Copy link
Contributor Author

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

mchr3k pushed a commit that referenced this issue Apr 13, 2014
@mchr3k
Copy link
Owner

mchr3k commented Apr 13, 2014

I have pushed a commit with a quick implementation of this issue.

@eostermueller
Copy link
Contributor Author

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;
        }
      }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants