3
  1. If a java class loaded at runtime as a bytecode (e.g. via ASM library or other mechanism), is it on a classpath of java? I don't see it.
  2. How to scan all annotations of classes loaded this way, if it's not on the java classpath?

I use google reflections and a custom classloader of a 3-rd party library.

Scanning for classes works as follows:

            Reflections reflections = new Reflections(ClasspathHelper.forPackage("com.mypackage",
                    MyCustomClassLoader),
                    new SubTypesScanner(), new TypeAnnotationsScanner());
Set<Class<?>> myClasses = reflections.getTypesAnnotatedWith(MyAnnotation.class);

MyAnnotation - is marked as @Retention(RetentionPolicy.RUNTIME). The above (in a class) is loaded dynamically at runtime by JVM.

As can be seen, behind the scenes, Reflections tries to get all URLs to be scanned using 2 classloaders by default static and context.

Reflection.scan()

Update: I have found an answer Can you find all classes in a package using reflection? saying that "If there are classes that get generated, or delivered remotely, you will not be able to discover those classes." But there is no proof, however. Can please anybody give more details on this and confirm?

Community
  • 1
  • 1
Ivan Voroshilin
  • 5,233
  • 3
  • 32
  • 61

1 Answers1

1

Dynamically instantiating classes at run time does not change the classpath that your JVM is using. What happens is that some ClassLoader class fetches bytecode from somewhere; and makes it "available" to you. But that does in no way change the "search order" for loading classes (and that is basically what the classpath is about: it only tells the JVM where and in which order to look for classes to load).

Meaning: any "loading" of a class results in some object of class java.lang.Class.

If you want to query the structure of any loaded class; you "just" need to get to the corresponding Class object. Class provides methods like getAnnotation(). It also provides methods to retrieve other objects that represent the methods and fields of the specific Class; and those objects can be queried for annotations in similar ways.

Update, regarding the updates in the question: there are situations where you don't have access to the file system where classes are coming from. You can load classes, when you know their name, but you have no way looking into the "place" where these classes live. And that basically breaks your ability to use reflection as intended.

There is no need to "prove" that, it is simply a consequence of the fact that Java allows you to load classes when you know there name, but "hides" the exact content of "where" those classes are coming from.

GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • Is there a way to get a classloader of such a class not using its reference, that is: SomeClass.class.getClassLoader(). I need to scan for annotations under a java-package, but I don't want to try all classloaders, it is slow – Ivan Voroshilin Apr 13 '15 at 06:47
  • I guess that depends on the library you are using. The **normal** thing should be that the result of a dynamic loading process ... is actually an object of class Class. So you might want to study the documentation on the library that you are using. Besides: if you already can type "SomeClass.class" - then you don't need the classloader, because SomeClass.class returns the Class object you are looking for. But of course, that only works for classes that are known at compile time. – GhostCat Apr 13 '15 at 07:09
  • I came to conclusion that a classloader can scans items only under its classpath. Annotations loaded at runtime, are not in the classpath. Thus the question is still open. – Ivan Voroshilin Apr 13 '15 at 07:53
  • You are not getting it: you do not need the ClassLoader. You have to understand how your library loads classes. As I told you: the Class object contains **all** structural information. Annotations, like anything else are in the Java classes; therefore you can get all required information this way. – GhostCat Apr 13 '15 at 08:06
  • Can you explain why I need to know how an annotated class is loaded. Yes, it is loaded somehow - This is sufficient. But scanning for it via google reflections doesn't work. And this library refer to classloaders to get a collection of all URLs. – Ivan Voroshilin Apr 13 '15 at 09:10
  • "It doesn't work" isn't a helpful description of your problem. You should turn back to your question and update it. Try to come up with a minimal example that shows your problem. Show us what you want to do; how you want to do it; and where it breaks. Nobody here has a crystal ball that tells us the solution to a problem we don't understand. – GhostCat Apr 13 '15 at 09:13