question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Methods of a class returned by ClassInfo.loadClass(), are annotated with strange method annotation instance

See original GitHub issue

I scanned classes with annotation, and iterate all methods of the class using getDeclaredMethod(). To find methods with an annotation, getting annotations of each method and checking if an instance of. It fails.

My application is running on Tomcat7, under WebappClassLoader environment.

problem

System.err.println(this.getClass().getClassLoader());

try (ScanResult scanResult = new ClassGraph().verbose()
        .whitelistPackages("jp.shoprun.ngapp.api")
        .enableAllInfo()
        .scan()) {
    ClassInfoList ngapiClasses = scanResult.getClassesWithAnnotation(AngularAPI.class.getName());
    for (String className : ngapiClasses.getNames()) {

        Class<?> clazz = scanResult.getClassInfo(className).loadClass();
        // Class<?> clazz = Class.forName(className); // It works.

        for (Method method : clazz.getDeclaredMethods()) {
            Annotation[] annotations = method.getAnnotations();
            if (annotations != null) {
                for (Annotation annotation : annotations) {

                    System.err.println(annotation);

                    if (annotation instanceof Path) { // 🐛 'Path' is my annotation. Methods annotated must be true, but not.
                        apiService.registerEntryPoint(clazz, method);
                        break;
                    }
                }
            }
        }
    }
}

println(classLoader) wrote:

WebappClassLoader
  context: /dev
  delegate: false
  repositories:
    /WEB-INF/classes/
----------> Parent Classloader:
java.net.URLClassLoader@14acaea5

println(annotation) wrote:

@jp.shoprun.system.webapi.ApiServlet$Path(value=/v1/weekly-schedule)

Annotation definitions

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface AngularAPI {
}

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Path {
    String value();
}

verbose() logs

2 22, 2019 5:06:03 午後 nonapi.io.github.classgraph.utils.LogNode flush
情報: 2019-02-22T17:06:02.961+0900    ClassGraph  ClassGraph version 4.8.5
2019-02-22T17:06:02.961+0900    ClassGraph  Operating system: Mac OS X 10.14.3 x86_64
2019-02-22T17:06:02.961+0900    ClassGraph  Java version: 1.8.0_201 / 1.8.0_201-b09 (Oracle Corporation)
2019-02-22T17:06:02.961+0900    ClassGraph  Java home: /Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/jre
2019-02-22T17:06:02.975+0900    ClassGraph  JRE rt.jar:
2019-02-22T17:06:02.975+0900    ClassGraph  -- /Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/jre/lib/rt.jar
2019-02-22T17:06:02.986+0900    ClassGraph  ScanSpec:
2019-02-22T17:06:02.986+0900    ClassGraph  -- packageWhiteBlackList: whitelist: ["jp.shoprun.stores.ngapp.api"]
2019-02-22T17:06:02.986+0900    ClassGraph  -- packagePrefixWhiteBlackList: whitelistPrefixes: ["jp.shoprun.ngapp.api."]
2019-02-22T17:06:02.987+0900    ClassGraph  -- pathWhiteBlackList: whitelist: ["jp/shoprun/ngapp/api/"]
2019-02-22T17:06:02.987+0900    ClassGraph  -- pathPrefixWhiteBlackList: whitelistPrefixes: ["jp/shoprun/ngapp/api/"]
2019-02-22T17:06:02.987+0900    ClassGraph  -- classWhiteBlackList: 
2019-02-22T17:06:02.987+0900    ClassGraph  -- classfilePathWhiteBlackList: 
2019-02-22T17:06:02.987+0900    ClassGraph  -- classPackageWhiteBlackList: 
2019-02-22T17:06:02.987+0900    ClassGraph  -- classPackagePathWhiteBlackList: 
2019-02-22T17:06:02.987+0900    ClassGraph  -- moduleWhiteBlackList: 
2019-02-22T17:06:02.987+0900    ClassGraph  -- jarWhiteBlackList: 
2019-02-22T17:06:02.987+0900    ClassGraph  -- classpathElementResourcePathWhiteBlackList: 
2019-02-22T17:06:02.987+0900    ClassGraph  -- libOrExtJarWhiteBlackList: 
2019-02-22T17:06:02.987+0900    ClassGraph  -- performScan: true
2019-02-22T17:06:02.987+0900    ClassGraph  -- scanJars: true
2019-02-22T17:06:02.987+0900    ClassGraph  -- scanNestedJars: true
2019-02-22T17:06:02.987+0900    ClassGraph  -- scanDirs: true
2019-02-22T17:06:02.987+0900    ClassGraph  -- scanModules: true
2019-02-22T17:06:02.988+0900    ClassGraph  -- enableClassInfo: true
2019-02-22T17:06:02.988+0900    ClassGraph  -- enableFieldInfo: true
2019-02-22T17:06:02.988+0900    ClassGraph  -- enableMethodInfo: true
2019-02-22T17:06:02.988+0900    ClassGraph  -- enableAnnotationInfo: true
2019-02-22T17:06:02.988+0900    ClassGraph  -- enableStaticFinalFieldConstantInitializerValues: true
2019-02-22T17:06:02.988+0900    ClassGraph  -- enableInterClassDependencies: false
2019-02-22T17:06:02.988+0900    ClassGraph  -- enableExternalClasses: false
2019-02-22T17:06:02.988+0900    ClassGraph  -- enableSystemJarsAndModules: false
2019-02-22T17:06:02.988+0900    ClassGraph  -- ignoreClassVisibility: true
2019-02-22T17:06:02.988+0900    ClassGraph  -- ignoreFieldVisibility: true
2019-02-22T17:06:02.988+0900    ClassGraph  -- ignoreMethodVisibility: true
2019-02-22T17:06:02.988+0900    ClassGraph  -- disableRuntimeInvisibleAnnotations: false
2019-02-22T17:06:02.988+0900    ClassGraph  -- extendScanningUpwardsToExternalClasses: true
2019-02-22T17:06:02.988+0900    ClassGraph  -- enableRemoteJarScanning: false
2019-02-22T17:06:02.988+0900    ClassGraph  -- addedClassLoaders: null
2019-02-22T17:06:02.988+0900    ClassGraph  -- overrideClassLoaders: null
2019-02-22T17:06:02.988+0900    ClassGraph  -- addedModuleLayers: null
2019-02-22T17:06:02.988+0900    ClassGraph  -- overrideModuleLayers: null
2019-02-22T17:06:02.988+0900    ClassGraph  -- overrideClasspath: null
2019-02-22T17:06:02.988+0900    ClassGraph  -- classpathElementFilters: null
2019-02-22T17:06:02.988+0900    ClassGraph  -- initializeLoadedClasses: false
2019-02-22T17:06:02.988+0900    ClassGraph  -- removeTemporaryFilesAfterScan: false
2019-02-22T17:06:02.989+0900    ClassGraph  -- ignoreParentClassLoaders: false
2019-02-22T17:06:02.989+0900    ClassGraph  -- ignoreParentModuleLayers: false
2019-02-22T17:06:02.989+0900    ClassGraph  -- modulePathInfo: 
2019-02-22T17:06:02.989+0900    ClassGraph  Number of worker threads: 14
2019-02-22T17:06:02.999+0900    ClassGraph  Finding classpath
2019-02-22T17:06:03.000+0900    ClassGraph  -- Finding classpath and modules
2019-02-22T17:06:03.000+0900    ClassGraph  ---- System jars:
2019-02-22T17:06:03.001+0900    ClassGraph  ------ Scanning disabled for rt.jar: /Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/jre/lib/rt.jar
2019-02-22T17:06:03.001+0900    ClassGraph  ------ Scanning disabled for lib or ext jar: /Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/lib/jconsole.jar

... (omit) ...

2019-02-22T17:06:03.002+0900    ClassGraph  ------ Scanning disabled for lib or ext jar: /Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/jre/lib/ext/jaccess.jar
2019-02-22T17:06:03.002+0900    ClassGraph  ------ Scanning disabled for lib or ext jar: /Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/jre/lib/ext/zipfs.jar
2019-02-22T17:06:03.002+0900    ClassGraph  ------ Scanning disabled for lib or ext jar: /System/Library/Java/Extensions/MRJToolkit.jar
2019-02-22T17:06:03.017+0900    ClassGraph  ---- Found ClassLoaders:
2019-02-22T17:06:03.017+0900    ClassGraph  ------ org.apache.catalina.loader.WebappClassLoader
2019-02-22T17:06:03.017+0900    ClassGraph  ---- Found system modules:
2019-02-22T17:06:03.017+0900    ClassGraph  ------ [None]
2019-02-22T17:06:03.017+0900    ClassGraph  ---- Found non-system modules:
2019-02-22T17:06:03.017+0900    ClassGraph  ------ [None]
2019-02-22T17:06:03.019+0900    ClassGraph  ---- ClassLoaderHandlers:
2019-02-22T17:06:03.098+0900    ClassGraph  ------ nonapi.io.github.classgraph.classloaderhandler.AntClassLoaderHandler
2019-02-22T17:06:03.098+0900    ClassGraph  ------ nonapi.io.github.classgraph.classloaderhandler.EquinoxClassLoaderHandler
2019-02-22T17:06:03.098+0900    ClassGraph  ------ nonapi.io.github.classgraph.classloaderhandler.EquinoxContextFinderClassLoaderHandler
2019-02-22T17:06:03.098+0900    ClassGraph  ------ nonapi.io.github.classgraph.classloaderhandler.FelixClassLoaderHandler
2019-02-22T17:06:03.098+0900    ClassGraph  ------ nonapi.io.github.classgraph.classloaderhandler.JBossClassLoaderHandler
2019-02-22T17:06:03.098+0900    ClassGraph  ------ nonapi.io.github.classgraph.classloaderhandler.WeblogicClassLoaderHandler
2019-02-22T17:06:03.098+0900    ClassGraph  ------ nonapi.io.github.classgraph.classloaderhandler.WebsphereLibertyClassLoaderHandler
2019-02-22T17:06:03.098+0900    ClassGraph  ------ nonapi.io.github.classgraph.classloaderhandler.WebsphereTraditionalClassLoaderHandler
2019-02-22T17:06:03.098+0900    ClassGraph  ------ nonapi.io.github.classgraph.classloaderhandler.OSGiDefaultClassLoaderHandler
2019-02-22T17:06:03.098+0900    ClassGraph  ------ nonapi.io.github.classgraph.classloaderhandler.SpringBootRestartClassLoaderHandler
2019-02-22T17:06:03.098+0900    ClassGraph  ------ nonapi.io.github.classgraph.classloaderhandler.TomcatWebappClassLoaderBaseHandler
2019-02-22T17:06:03.098+0900    ClassGraph  ------ nonapi.io.github.classgraph.classloaderhandler.ParentLastDelegationOrderTestClassLoaderHandler
2019-02-22T17:06:03.098+0900    ClassGraph  ------ nonapi.io.github.classgraph.classloaderhandler.JPMSClassLoaderHandler
2019-02-22T17:06:03.098+0900    ClassGraph  ------ nonapi.io.github.classgraph.classloaderhandler.URLClassLoaderHandler
2019-02-22T17:06:03.098+0900    ClassGraph  ---- ClassLoader org.apache.catalina.loader.WebappClassLoader will be handled by nonapi.io.github.classgraph.classloaderhandler.TomcatWebappClassLoaderBaseHandler@2dc35408
2019-02-22T17:06:03.100+0900    ClassGraph  ---- org.apache.catalina.loader.WebappClassLoader delegates to parent java.net.URLClassLoader with order PARENT_FIRST
2019-02-22T17:06:03.104+0900    ClassGraph  ---- ClassLoader java.net.URLClassLoader will be handled by nonapi.io.github.classgraph.classloaderhandler.URLClassLoaderHandler@63d37070
2019-02-22T17:06:03.104+0900    ClassGraph  ---- java.net.URLClassLoader delegates to parent sun.misc.Launcher$AppClassLoader with order PARENT_FIRST
2019-02-22T17:06:03.104+0900    ClassGraph  ---- ClassLoader sun.misc.Launcher$AppClassLoader will be handled by nonapi.io.github.classgraph.classloaderhandler.URLClassLoaderHandler@625fc09d
2019-02-22T17:06:03.104+0900    ClassGraph  ---- sun.misc.Launcher$AppClassLoader delegates to parent sun.misc.Launcher$ExtClassLoader with order PARENT_FIRST
2019-02-22T17:06:03.104+0900    ClassGraph  ---- ClassLoader sun.misc.Launcher$ExtClassLoader will be handled by nonapi.io.github.classgraph.classloaderhandler.URLClassLoaderHandler@eaccbd2
2019-02-22T17:06:03.105+0900    ClassGraph  ---- Finding classpath elements in ClassLoaders
2019-02-22T17:06:03.105+0900    ClassGraph  ------ Finding classpath elements in ClassLoader sun.misc.Launcher$ExtClassLoader
2019-02-22T17:06:03.105+0900    ClassGraph  -------- Ignoring duplicate classpath element: file:/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/jre/lib/ext/sunec.jar -> /Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/jre/lib/ext/sunec.jar
2019-02-22T17:06:03.105+0900    ClassGraph  -------- Ignoring duplicate classpath element: file:/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/jre/lib/ext/nashorn.jar -> /Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/jre/lib/ext/nashorn.jar

... (omit) ...

2019-02-22T17:06:03.283+0900    ClassGraph  Opening classpath elements (took 0.245446 sec)
2019-02-22T17:06:03.542+0900    ClassGraph  -- Scanning directory classpath element /Users/kensuke/git/shoprun/Stores/bin (took 0.046641 sec)
2019-02-22T17:06:03.573+0900    ClassGraph  ---- Scanning directory: /Users/kensuke/git/shoprun/Stores/bin (took 0.016351 sec)
2019-02-22T17:06:03.577+0900    ClassGraph  ------ Scanning directory: /Users/kensuke/git/shoprun/Stores/bin/jp (took 0.011671 sec)
2019-02-22T17:06:03.578+0900    ClassGraph  -------- Scanning directory: /Users/kensuke/git/shoprun/Stores/bin/jp/shoprun (took 0.011217 sec)
2019-02-22T17:06:03.585+0900    ClassGraph  ------------ Scanning directory: /Users/kensuke/git/shoprun/Stores/bin/jp/shoprun/ngapp (took 0.002829 sec)
2019-02-22T17:06:03.585+0900    ClassGraph  -------------- Scanning directory: /Users/kensuke/git/shoprun/Stores/bin/jp/shoprun/ngapp/api (took 0.002485 sec)
2019-02-22T17:06:03.587+0900    ClassGraph  ---------------- Found classfile within whitelisted package: jp/shoprun/ngapp/api/AbstractAngularAPI.class
2019-02-22T17:06:03.636+0900    ClassGraph  ------------------ Parsing classfile (took 0.064778 sec)
2019-02-22T17:06:03.674+0900    ClassGraph  -------------------- Found class jp.shoprun.ngapp.api.AbstractAngularAPI
2019-02-22T17:06:03.674+0900    ClassGraph  ---------------------- Superclass: java.lang.Object
2019-02-22T17:06:03.700+0900    ClassGraph  ---------------------- Method: public <init>()
2019-02-22T17:06:03.700+0900    ClassGraph  ---------------------- Method: protected jp.shoprun.session.Session verifySession(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
2019-02-22T17:06:03.587+0900    ClassGraph  ---------------- Found classfile within whitelisted package: jp/shoprun/ngapp/api/JSONConverter.class
2019-02-22T17:06:03.638+0900    ClassGraph  ------------------ Parsing classfile (took 0.063699 sec)
2019-02-22T17:06:03.671+0900    ClassGraph  -------------------- Scheduling external class for scanning: method annotation jp.shoprun.session.ThreadLocalDepended -- found in classpath element /Users/kensuke/git/shoprun/Core/webroot/WEB-INF/classes

❗NGCalendarAPI is my annotated class !!
2019-02-22T17:06:03.587+0900    ClassGraph  ---------------- Found classfile within whitelisted package: jp/shoprun/ngapp/api/NGCalendarAPI.class
2019-02-22T17:06:03.639+0900    ClassGraph  ------------------ Parsing classfile (took 0.068372 sec)
2019-02-22T17:06:03.689+0900    ClassGraph  -------------------- Found class jp.shoprun.stores.ngapp.api.NGCalendarAPI
2019-02-22T17:06:03.689+0900    ClassGraph  ---------------------- Superclass: jp.shoprun.stores.ngapp.api.AbstractAngularAPI
2019-02-22T17:06:03.689+0900    ClassGraph  ---------------------- Class annotations: @jp.shoprun.system.webapi.ApiServlet$AngularAPI
2019-02-22T17:06:03.689+0900    ClassGraph  ---------------------- Field: private static final org.apache.commons.logging.Log LOG
2019-02-22T17:06:03.700+0900    ClassGraph  ---------------------- Method: static void <clinit>()
2019-02-22T17:06:03.700+0900    ClassGraph  ---------------------- Method: public <init>()

❗NGCalendarAPI has public methods with annotation !!

2019-02-22T17:06:03.701+0900    ClassGraph  ---------------------- Method: @jp.shoprun.system.webapi.ApiServlet$Path("/v1/weekly-schedule") @jp.shoprun.system.webapi.ApiServlet$GET public java.util.Map<java.lang.String, java.lang.Object> weeklySchedule(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, @jp.shoprun.system.webapi.ApiServlet$Param("colorsId") java.lang.String, @jp.shoprun.system.webapi.ApiServlet$Param("y4md") java.lang.String, @jp.shoprun.system.webapi.ApiServlet$Param("filterId") java.lang.String, @jp.shoprun.system.webapi.ApiServlet$Param("pubGroup") java.lang.String, @jp.shoprun.system.webapi.ApiServlet$Param("showsHidden") boolean, @jp.shoprun.system.webapi.ApiServlet$Param("showsStoreManagerOnlyNotices") boolean)
2019-02-22T17:06:03.701+0900    ClassGraph  ---------------------- Method: @jp.shoprun.system.webapi.ApiServlet$Path("/v1/weekly-calendar") @jp.shoprun.system.webapi.ApiServlet$GET public java.util.Map<java.lang.String, java.lang.Object> weeklyCalendar(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, @jp.shoprun.system.webapi.ApiServlet$Param("view") java.lang.String, @jp.shoprun.system.webapi.ApiServlet$Param("colorsId") java.lang.String, @jp.shoprun.system.webapi.ApiServlet$Param("y4md") java.lang.String, @jp.shoprun.system.webapi.ApiServlet$Param("filterId") java.lang.String, @jp.shoprun.system.webapi.ApiServlet$Param("pubGroup") java.lang.String, @jp.shoprun.system.webapi.ApiServlet$Param("showsHidden") boolean, @jp.shoprun.system.webapi.ApiServlet$Param("showsStoreManagerOnlyNotices") boolean)
2019-02-22T17:06:03.702+0900    ClassGraph  ---------------------- Method: @jp.shoprun.system.webapi.ApiServlet$Path("/v1/monthly-calendar") @jp.shoprun.system.webapi.ApiServlet$GET public java.util.Map<java.lang.String, java.lang.Object> monthlyCalendar(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, @jp.shoprun.system.webapi.ApiServlet$Param("view") java.lang.String, @jp.shoprun.system.webapi.ApiServlet$Param("colorsId") java.lang.String, @jp.shoprun.system.webapi.ApiServlet$Param("y4m") java.lang.String, @jp.shoprun.system.webapi.ApiServlet$Param("filterId") java.lang.String, @jp.shoprun.system.webapi.ApiServlet$Param("pubGroup") java.lang.String, @jp.shoprun.system.webapi.ApiServlet$Param("showsHidden") boolean, @jp.shoprun.system.webapi.ApiServlet$Param("showsStoreManagerOnlyNotices") boolean)
2019-02-22T17:06:03.703+0900    ClassGraph  ---------------------- Method: private java.util.Map<java.lang.String, java.lang.Object> makeWeeklyScheduleJSON(jp.shoprun.calendar.RenderingContext, jp.shoprun.stores.calendar.WeeklyScheduleCalendarUnit)

list private methods
... (omit) ...

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:9 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
lukehutchcommented, Feb 22, 2019

Yes, it looks like this is the problem then. You have two Path classes loaded by different classloaders, and even if the class definition is exactly the same, the two classes cannot be cast to each other, because they are loaded into different classloaders.

It is possible that the order in which classloaders are tried is wrong. Please set a breakpoint at the entrance to .loadClass(), or directly at the class io.github.classgraph.ClassGraphClassLoader, in the method findClass(String className):

https://github.com/classgraph/classgraph/blob/master/src/main/java/io/github/classgraph/ClassGraphClassLoader.java#L60

Step through the lines of findClass, and determine which of the classloading options actually succeeded in your runtime environment.

Then clone the ClassGraph project and set up a Maven project in your IDE. Disable the classloading option that succeeded by commenting that code out, and rebuild ClassGraph.

If commenting out the classloading code that caused the class to be loaded by AppClassLoader causes the annotation to be successfully loaded by WebappClassLoader, then the order of lines in findClass should probably be changed, at least to fix this problem with Tomcat. I just hope that that doesn’t break classloading for some other environment.

0reactions
lukehutchcommented, Feb 22, 2019

@nebosuke Great, thanks for testing! Released as 4.8.6.

Read more comments on GitHub >

github_iconTop Results From Across the Web

AnnotationInfo (ClassGraph 4.8.44 API) - javadoc.io
Holds metadata about a specific annotation instance on a class, method, method parameter or field. ... Return the ClassInfo object for the annotation...
Read more >
Can you annotate return type when value is instance of cls?
The bound argument specifies that T has to be a (subclass of) TrivialClass ; because the class doesn't yet exist when you define...
Read more >
Bug Patterns - Error Prone
Dagger @Provides methods may not return null unless annotated with @Nullable ... Calling getClass() on an annotation may return a proxy class.
Read more >
io.github.classgraph.ClassInfo.loadClass java code examples
Popular methods of ClassInfo · getName · isInterface · getAnnotationInfo. Get a the named annotation on this class, or null if the class...
Read more >
Effective Dart: Design
For example, elementAt() returns a piece of data from a collection, ... This means the member is syntactically a method, but conceptually it...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found