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

Change in enableSystemJarsAndModules behaviour #658

Open
cushon opened this issue Mar 1, 2022 · 3 comments
Open

Change in enableSystemJarsAndModules behaviour #658

cushon opened this issue Mar 1, 2022 · 3 comments

Comments

@cushon
Copy link
Contributor

cushon commented Mar 1, 2022

The following demo used to be able to find classes in jdk.compiler, but it fails with recent versions of classgraph.

The change bisects to 718bcba.

Adding .enableSystemJarsAndModules() allows it to work with the latest version of classgraph.

I'm fine with passing enableSystemJarsAndModules(), I just wanted to double-check if this was an expected result of that change?

import com.sun.source.tree.Tree;
import io.github.classgraph.ClassGraph;
import io.github.classgraph.ClassInfo;
import io.github.classgraph.ScanResult;

import java.util.ArrayList;
import java.util.List;

public class CG {
  public static void main(String[] args) {
    try (ScanResult scanResult =
        new ClassGraph()
            .enableClassInfo()
            .acceptModules("jdk.compiler")
            .acceptModules(Tree.class.getModule().getName())
            .acceptPackages(Tree.class.getPackage().getName())
            .scan()) {
      List<Class<?>> classes = new ArrayList<>();
      for (ClassInfo classInfo : scanResult.getAllInterfaces()) {
        classes.add(classInfo.loadClass());
      }
      if (classes.size() < 3) {
        throw new AssertionError();
      } else {
        System.err.println(classes.get(0) + " " + classes.size());
      }
    }
  }
}
@lukehutch
Copy link
Member

Hey @cushon,

I took a look at this, and there is another issue in addition to the one you pointed out -- currently the accept/reject logic doesn't work the same for modules as it does for packages etc. (Specifically if you mark at least one module for scanning using .acceptModules(...), it should scan only that module, not all modules.)

I think I need to revamp the whole accept/reject system, since this is needed to fix #643 too. It might take me a while to do this. I'm glad you have found a workaround for this, for the meantime.

However thinking more specifically about your question, I'm not sure if the old behavior that you were used to (where even if .enableSystemJarsAndModules() has not been called, if you call .acceptModules(moduleName) with a system module name, it would scan that one system module) would match the intent of .enableSystemJarsAndModules(). The purpose of .enableSystemJarsAndModules() is that the system jar (rt.jar before Java 9) and the system modules (Java 9+) are very large, and the overhead of scanning those modules should not be incurred unless the user specifically requests scanning them.

Maybe the right thing to do is to have ClassGraph automatically call .enableSystemJarsAndModules() if a package or module name is requested to be scanned, and that package or module name matches system package/module name criteria? I think that would fix your usecase at least, and it wouldn't cause other users overhead. (I'm not sure why this worked before the bisect point you provided, I'd have to step through a running example and think about it...)

@cushon
Copy link
Contributor Author

cushon commented Apr 19, 2022

Thanks for taking a look! I don't really have an opinion about the best approach here.

Maybe the right thing to do is to have ClassGraph automatically call .enableSystemJarsAndModules() if a package or module name is requested to be scanned, and that package or module name matches system package/module name criteria?

That would be convenient, but is there a good way to detecting which module and package names are system ones, without doing the work .enableSystemJarsAndModules() is doing? Is the idea to check for java.* and other well-known prefixes?

@lukehutch
Copy link
Member

Correct, I'd have to detect module name prefixes java.* and jdk.*, there's no other way to test for this, unless maybe it's possible to look up the module and check if the module layer is a system module layer.

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