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

Don't allow PlatformClassLoader or AppClassLoader as override classloaders #795

Open
mgroth0 opened this issue Sep 24, 2023 · 10 comments
Open

Comments

@mgroth0
Copy link

mgroth0 commented Sep 24, 2023

Hello, first of all thanks for the great library. Its really a pleasure using it.

I'm having an issue and have been searching this repo for answers. I found #639 and that seems to be closely related to my current issue.

I am overriding the classloaders with jdk.internal.loader.ClassLoaders$AppClassLoader. I expcted to get all of my classes, but the the list of classes returned is empty. At this point, I felt confused and knew something was wrong.

This seemed wrong because clearly many classes were loaded with the system classloader. I checked and made sure, and in fact all of the classes I was looking for were loaded from it.

Eventually, I disabled ignoreParentClassLoaders, and then it worked as expected.

This seems to be a consequence of this line:

if ((!scanSpec.ignoreParentClassLoaders && (scanSpec.overrideClassLoaders == null || forceScanJavaClassPath)

It seems like there have been issues with the system classloader, and that these issues have been addressed but only for when ignoreParentClassLoaders is false. However, I think many new users such as myself might intuitively use ignoreParentClassLoaders with the System classloader in an attempt to avoid using the platform classloader.

So there is a perfectly fine workaround, but I think something might be inconsistent here in the library. I think if we configure ClassGraph to use only the system classoader but to "ignore parent classloaders", I think we would expect it to get just that- all the classed loaded by the System classloader without the platform classes loaded with the platform loader.

After finding the option enableSystemJarsAndModules(), I realized that platform classes are not loaded by default. That makes it so I no longer need to use ignoreParentClassLoaders. So my workaround of just not using ignoreParentClassLoaders is perfectly fine. but I just think maybe there should be a warning or error for users who try to do what I did otherwise our expectations would not be met leading to confusion.

Using classgraph version 4.8.162.

One thing I think that really clarifies this issue to me is that in the log, this statement is inconsistent:

2023-09-23T22:03:45.520-0400	ClassGraph	---- overrideClassLoaders() was called with an instance of jdk.internal.loader.ClassLoaders$AppClassLoader, which is a system classloader, so enableSystemJarsAndModules() was called automatically
2023-09-23T22:03:45.520-0400	ClassGraph	---- overrideClassLoaders() was called with an instance of jdk.internal.loader.ClassLoaders$AppClassLoader, which is a system classloader, so the `java.lang.path` classpath will also be scanned

So the log says that it notices we used the System classloader and did an automatic fix for it. (I think the log has a typo, it says java.lang.path but I think it meant java.class.path?) But the according to the source code, I should expect to see the line Getting classpath entries from java.class.path in my logs, but I never do.

Sep 23, 2023 10:03:45 PM nonapi.io.github.classgraph.utils.LogNode flush
INFO: 2023-09-23T22:03:45.513-0400	ClassGraph	ClassGraph version 4.8.162
2023-09-23T22:03:45.513-0400	ClassGraph	Operating system: Mac OS X 13.5.2 aarch64
2023-09-23T22:03:45.513-0400	ClassGraph	Java version: 17.0.6 / 17.0.6+10-LTS (Azul Systems, Inc.)
2023-09-23T22:03:45.513-0400	ClassGraph	Java home: /Users/matthewgroth/Library/Java/JavaVirtualMachines/azul-17.0.6/Contents/Home
2023-09-23T22:03:45.517-0400	ClassGraph	ScanSpec:
2023-09-23T22:03:45.517-0400	ClassGraph	-- packageAcceptReject: 
2023-09-23T22:03:45.517-0400	ClassGraph	-- packagePrefixAcceptReject: 
2023-09-23T22:03:45.517-0400	ClassGraph	-- pathAcceptReject: 
2023-09-23T22:03:45.517-0400	ClassGraph	-- pathPrefixAcceptReject: 
2023-09-23T22:03:45.517-0400	ClassGraph	-- classAcceptReject: 
2023-09-23T22:03:45.517-0400	ClassGraph	-- classfilePathAcceptReject: 
2023-09-23T22:03:45.517-0400	ClassGraph	-- classPackageAcceptReject: 
2023-09-23T22:03:45.517-0400	ClassGraph	-- classPackagePathAcceptReject: 
2023-09-23T22:03:45.517-0400	ClassGraph	-- moduleAcceptReject: 
2023-09-23T22:03:45.517-0400	ClassGraph	-- jarAcceptReject: 
2023-09-23T22:03:45.517-0400	ClassGraph	-- classpathElementResourcePathAcceptReject: 
2023-09-23T22:03:45.517-0400	ClassGraph	-- libOrExtJarAcceptReject: 
2023-09-23T22:03:45.517-0400	ClassGraph	-- scanJars: true
2023-09-23T22:03:45.517-0400	ClassGraph	-- scanNestedJars: true
2023-09-23T22:03:45.517-0400	ClassGraph	-- scanDirs: true
2023-09-23T22:03:45.517-0400	ClassGraph	-- scanModules: false
2023-09-23T22:03:45.517-0400	ClassGraph	-- enableClassInfo: true
2023-09-23T22:03:45.517-0400	ClassGraph	-- enableFieldInfo: false
2023-09-23T22:03:45.517-0400	ClassGraph	-- enableMethodInfo: false
2023-09-23T22:03:45.517-0400	ClassGraph	-- enableAnnotationInfo: false
2023-09-23T22:03:45.517-0400	ClassGraph	-- enableStaticFinalFieldConstantInitializerValues: false
2023-09-23T22:03:45.517-0400	ClassGraph	-- enableInterClassDependencies: false
2023-09-23T22:03:45.517-0400	ClassGraph	-- enableExternalClasses: false
2023-09-23T22:03:45.517-0400	ClassGraph	-- enableSystemJarsAndModules: false
2023-09-23T22:03:45.517-0400	ClassGraph	-- ignoreClassVisibility: true
2023-09-23T22:03:45.517-0400	ClassGraph	-- ignoreFieldVisibility: false
2023-09-23T22:03:45.517-0400	ClassGraph	-- ignoreMethodVisibility: false
2023-09-23T22:03:45.517-0400	ClassGraph	-- disableRuntimeInvisibleAnnotations: false
2023-09-23T22:03:45.517-0400	ClassGraph	-- extendScanningUpwardsToExternalClasses: true
2023-09-23T22:03:45.517-0400	ClassGraph	-- allowedURLSchemes: null
2023-09-23T22:03:45.517-0400	ClassGraph	-- addedClassLoaders: null
2023-09-23T22:03:45.517-0400	ClassGraph	-- overrideClassLoaders: [jdk.internal.loader.ClassLoaders$AppClassLoader@531d72ca]
2023-09-23T22:03:45.517-0400	ClassGraph	-- addedModuleLayers: null
2023-09-23T22:03:45.518-0400	ClassGraph	-- overrideModuleLayers: null
2023-09-23T22:03:45.518-0400	ClassGraph	-- overrideClasspath: null
2023-09-23T22:03:45.518-0400	ClassGraph	-- classpathElementFilters: null
2023-09-23T22:03:45.518-0400	ClassGraph	-- initializeLoadedClasses: false
2023-09-23T22:03:45.518-0400	ClassGraph	-- removeTemporaryFilesAfterScan: false
2023-09-23T22:03:45.518-0400	ClassGraph	-- ignoreParentClassLoaders: true
2023-09-23T22:03:45.518-0400	ClassGraph	-- ignoreParentModuleLayers: false
2023-09-23T22:03:45.518-0400	ClassGraph	-- modulePathInfo: 
2023-09-23T22:03:45.518-0400	ClassGraph	-- maxBufferedJarRAMSize: 67108864
2023-09-23T22:03:45.518-0400	ClassGraph	-- enableMemoryMapping: true
2023-09-23T22:03:45.518-0400	ClassGraph	-- enableMultiReleaseVersions: false
2023-09-23T22:03:45.518-0400	ClassGraph	Number of worker threads: 17
2023-09-23T22:03:45.520-0400	ClassGraph	Finding classpath
2023-09-23T22:03:45.520-0400	ClassGraph	-- Finding classpath and modules
2023-09-23T22:03:45.520-0400	ClassGraph	---- overrideClassLoaders() was called with an instance of jdk.internal.loader.ClassLoaders$AppClassLoader, which is a system classloader, so enableSystemJarsAndModules() was called automatically
2023-09-23T22:03:45.520-0400	ClassGraph	---- overrideClassLoaders() was called with an instance of jdk.internal.loader.ClassLoaders$AppClassLoader, which is a system classloader, so the `java.lang.path` classpath will also be scanned
2023-09-23T22:03:45.530-0400	ClassGraph	---- System modules found:
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module java.base, location=jrt:/java.base]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module java.compiler, location=jrt:/java.compiler]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module java.datatransfer, location=jrt:/java.datatransfer]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module java.desktop, location=jrt:/java.desktop]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module java.instrument, location=jrt:/java.instrument]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module java.logging, location=jrt:/java.logging]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module java.management, location=jrt:/java.management]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module java.management.rmi, location=jrt:/java.management.rmi]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module java.naming, location=jrt:/java.naming]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module java.net.http, location=jrt:/java.net.http]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module java.prefs, location=jrt:/java.prefs]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module java.rmi, location=jrt:/java.rmi]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module java.scripting, location=jrt:/java.scripting]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module java.security.jgss, location=jrt:/java.security.jgss]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module java.security.sasl, location=jrt:/java.security.sasl]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module java.smartcardio, location=jrt:/java.smartcardio]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module java.sql, location=jrt:/java.sql]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module java.sql.rowset, location=jrt:/java.sql.rowset]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module java.transaction.xa, location=jrt:/java.transaction.xa]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module java.xml, location=jrt:/java.xml]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module java.xml.crypto, location=jrt:/java.xml.crypto]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module jdk.accessibility, location=jrt:/jdk.accessibility]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module jdk.attach, location=jrt:/jdk.attach]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module jdk.charsets, location=jrt:/jdk.charsets]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module jdk.compiler, location=jrt:/jdk.compiler]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module jdk.crypto.cryptoki, location=jrt:/jdk.crypto.cryptoki]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module jdk.crypto.ec, location=jrt:/jdk.crypto.ec]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module jdk.dynalink, location=jrt:/jdk.dynalink]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module jdk.editpad, location=jrt:/jdk.editpad]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module jdk.httpserver, location=jrt:/jdk.httpserver]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module jdk.internal.ed, location=jrt:/jdk.internal.ed]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module jdk.internal.jvmstat, location=jrt:/jdk.internal.jvmstat]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module jdk.internal.le, location=jrt:/jdk.internal.le]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module jdk.internal.opt, location=jrt:/jdk.internal.opt]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module jdk.jartool, location=jrt:/jdk.jartool]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module jdk.javadoc, location=jrt:/jdk.javadoc]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module jdk.jconsole, location=jrt:/jdk.jconsole]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module jdk.jdeps, location=jrt:/jdk.jdeps]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module jdk.jdi, location=jrt:/jdk.jdi]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module jdk.jdwp.agent, location=jrt:/jdk.jdwp.agent]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module jdk.jfr, location=jrt:/jdk.jfr]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module jdk.jlink, location=jrt:/jdk.jlink]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module jdk.jpackage, location=jrt:/jdk.jpackage]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module jdk.jshell, location=jrt:/jdk.jshell]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module jdk.jsobject, location=jrt:/jdk.jsobject]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module jdk.jstatd, location=jrt:/jdk.jstatd]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module jdk.localedata, location=jrt:/jdk.localedata]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module jdk.management, location=jrt:/jdk.management]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module jdk.management.agent, location=jrt:/jdk.management.agent]
2023-09-23T22:03:45.530-0400	ClassGraph	------ [module jdk.management.jfr, location=jrt:/jdk.management.jfr]
2023-09-23T22:03:45.531-0400	ClassGraph	------ [module jdk.naming.dns, location=jrt:/jdk.naming.dns]
2023-09-23T22:03:45.531-0400	ClassGraph	------ [module jdk.naming.rmi, location=jrt:/jdk.naming.rmi]
2023-09-23T22:03:45.531-0400	ClassGraph	------ [module jdk.net, location=jrt:/jdk.net]
2023-09-23T22:03:45.531-0400	ClassGraph	------ [module jdk.nio.mapmode, location=jrt:/jdk.nio.mapmode]
2023-09-23T22:03:45.531-0400	ClassGraph	------ [module jdk.random, location=jrt:/jdk.random]
2023-09-23T22:03:45.531-0400	ClassGraph	------ [module jdk.sctp, location=jrt:/jdk.sctp]
2023-09-23T22:03:45.531-0400	ClassGraph	------ [module jdk.security.auth, location=jrt:/jdk.security.auth]
2023-09-23T22:03:45.531-0400	ClassGraph	------ [module jdk.security.jgss, location=jrt:/jdk.security.jgss]
2023-09-23T22:03:45.531-0400	ClassGraph	------ [module jdk.unsupported, location=jrt:/jdk.unsupported]
2023-09-23T22:03:45.531-0400	ClassGraph	------ [module jdk.unsupported.desktop, location=jrt:/jdk.unsupported.desktop]
2023-09-23T22:03:45.531-0400	ClassGraph	------ [module jdk.xml.dom, location=jrt:/jdk.xml.dom]
2023-09-23T22:03:45.531-0400	ClassGraph	------ [module jdk.zipfs, location=jrt:/jdk.zipfs]
2023-09-23T22:03:45.531-0400	ClassGraph	---- Scanning of non-system modules is not enabled
2023-09-23T22:03:45.535-0400	ClassGraph	---- System jars:
2023-09-23T22:03:45.535-0400	ClassGraph	------ Scanning disabled for lib or ext jar: /Users/matthewgroth/Library/Java/JavaVirtualMachines/azul-17.0.6/Contents/Home/lib/jrt-fs.jar
2023-09-23T22:03:45.535-0400	ClassGraph	---- ClassLoaderHandlers:
2023-09-23T22:03:45.535-0400	ClassGraph	------ nonapi.io.github.classgraph.classloaderhandler.AntClassLoaderHandler
2023-09-23T22:03:45.535-0400	ClassGraph	------ nonapi.io.github.classgraph.classloaderhandler.EquinoxClassLoaderHandler
2023-09-23T22:03:45.535-0400	ClassGraph	------ nonapi.io.github.classgraph.classloaderhandler.EquinoxContextFinderClassLoaderHandler
2023-09-23T22:03:45.535-0400	ClassGraph	------ nonapi.io.github.classgraph.classloaderhandler.FelixClassLoaderHandler
2023-09-23T22:03:45.535-0400	ClassGraph	------ nonapi.io.github.classgraph.classloaderhandler.JBossClassLoaderHandler
2023-09-23T22:03:45.535-0400	ClassGraph	------ nonapi.io.github.classgraph.classloaderhandler.WeblogicClassLoaderHandler
2023-09-23T22:03:45.535-0400	ClassGraph	------ nonapi.io.github.classgraph.classloaderhandler.WebsphereLibertyClassLoaderHandler
2023-09-23T22:03:45.535-0400	ClassGraph	------ nonapi.io.github.classgraph.classloaderhandler.WebsphereTraditionalClassLoaderHandler
2023-09-23T22:03:45.535-0400	ClassGraph	------ nonapi.io.github.classgraph.classloaderhandler.OSGiDefaultClassLoaderHandler
2023-09-23T22:03:45.535-0400	ClassGraph	------ nonapi.io.github.classgraph.classloaderhandler.SpringBootRestartClassLoaderHandler
2023-09-23T22:03:45.535-0400	ClassGraph	------ nonapi.io.github.classgraph.classloaderhandler.TomcatWebappClassLoaderBaseHandler
2023-09-23T22:03:45.535-0400	ClassGraph	------ nonapi.io.github.classgraph.classloaderhandler.CxfContainerClassLoaderHandler
2023-09-23T22:03:45.535-0400	ClassGraph	------ nonapi.io.github.classgraph.classloaderhandler.PlexusClassWorldsClassRealmClassLoaderHandler
2023-09-23T22:03:45.535-0400	ClassGraph	------ nonapi.io.github.classgraph.classloaderhandler.QuarkusClassLoaderHandler
2023-09-23T22:03:45.535-0400	ClassGraph	------ nonapi.io.github.classgraph.classloaderhandler.UnoOneJarClassLoaderHandler
2023-09-23T22:03:45.535-0400	ClassGraph	------ nonapi.io.github.classgraph.classloaderhandler.ParentLastDelegationOrderTestClassLoaderHandler
2023-09-23T22:03:45.535-0400	ClassGraph	------ nonapi.io.github.classgraph.classloaderhandler.JPMSClassLoaderHandler
2023-09-23T22:03:45.535-0400	ClassGraph	------ nonapi.io.github.classgraph.classloaderhandler.URLClassLoaderHandler
2023-09-23T22:03:45.535-0400	ClassGraph	------ nonapi.io.github.classgraph.classloaderhandler.ClassGraphClassLoaderHandler
2023-09-23T22:03:45.535-0400	ClassGraph	---- Finding unique classloaders in delegation order
2023-09-23T22:03:45.536-0400	ClassGraph	---- Obtaining URLs from classloaders in delegation order
2023-09-23T22:03:45.536-0400	ClassGraph	------ Ignoring parent classloader jdk.internal.loader.ClassLoaders$PlatformClassLoader@45f4a7c1, normally handled by nonapi.io.github.classgraph.classloaderhandler.JPMSClassLoaderHandler
2023-09-23T22:03:45.536-0400	ClassGraph	------ Classloader jdk.internal.loader.ClassLoaders$AppClassLoader is handled by nonapi.io.github.classgraph.classloaderhandler.JPMSClassLoaderHandler
2023-09-23T22:03:45.537-0400	ClassGraph	-- Skipping module, since module scanning is disabled: java.base
2023-09-23T22:03:45.537-0400	ClassGraph	-- Skipping module, since module scanning is disabled: java.compiler
2023-09-23T22:03:45.537-0400	ClassGraph	-- Skipping module, since module scanning is disabled: java.datatransfer
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: java.desktop
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: java.instrument
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: java.logging
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: java.management
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: java.management.rmi
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: java.naming
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: java.net.http
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: java.prefs
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: java.rmi
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: java.scripting
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: java.security.jgss
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: java.security.sasl
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: java.smartcardio
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: java.sql
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: java.sql.rowset
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: java.transaction.xa
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: java.xml
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: java.xml.crypto
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: jdk.accessibility
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: jdk.attach
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: jdk.charsets
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: jdk.compiler
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: jdk.crypto.cryptoki
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: jdk.crypto.ec
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: jdk.dynalink
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: jdk.editpad
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: jdk.httpserver
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: jdk.internal.ed
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: jdk.internal.jvmstat
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: jdk.internal.le
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: jdk.internal.opt
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: jdk.jartool
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: jdk.javadoc
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: jdk.jconsole
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: jdk.jdeps
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: jdk.jdi
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: jdk.jdwp.agent
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: jdk.jfr
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: jdk.jlink
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: jdk.jpackage
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: jdk.jshell
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: jdk.jsobject
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: jdk.jstatd
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: jdk.localedata
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: jdk.management
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: jdk.management.agent
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: jdk.management.jfr
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: jdk.naming.dns
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: jdk.naming.rmi
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: jdk.net
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: jdk.nio.mapmode
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: jdk.random
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: jdk.sctp
2023-09-23T22:03:45.538-0400	ClassGraph	-- Skipping module, since module scanning is disabled: jdk.security.auth
2023-09-23T22:03:45.539-0400	ClassGraph	-- Skipping module, since module scanning is disabled: jdk.security.jgss
2023-09-23T22:03:45.539-0400	ClassGraph	-- Skipping module, since module scanning is disabled: jdk.unsupported
2023-09-23T22:03:45.539-0400	ClassGraph	-- Skipping module, since module scanning is disabled: jdk.unsupported.desktop
2023-09-23T22:03:45.539-0400	ClassGraph	-- Skipping module, since module scanning is disabled: jdk.xml.dom
2023-09-23T22:03:45.539-0400	ClassGraph	-- Skipping module, since module scanning is disabled: jdk.zipfs
2023-09-23T22:03:45.540-0400	ClassGraph	Opening classpath elements (took 0.000722 sec)
2023-09-23T22:03:45.540-0400	ClassGraph	Finding nested classpath elements
2023-09-23T22:03:45.541-0400	ClassGraph	Final classpath element order:
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module java.base, location=jrt:/java.base]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module java.compiler, location=jrt:/java.compiler]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module java.datatransfer, location=jrt:/java.datatransfer]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module java.desktop, location=jrt:/java.desktop]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module java.instrument, location=jrt:/java.instrument]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module java.logging, location=jrt:/java.logging]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module java.management, location=jrt:/java.management]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module java.management.rmi, location=jrt:/java.management.rmi]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module java.naming, location=jrt:/java.naming]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module java.net.http, location=jrt:/java.net.http]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module java.prefs, location=jrt:/java.prefs]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module java.rmi, location=jrt:/java.rmi]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module java.scripting, location=jrt:/java.scripting]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module java.security.jgss, location=jrt:/java.security.jgss]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module java.security.sasl, location=jrt:/java.security.sasl]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module java.smartcardio, location=jrt:/java.smartcardio]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module java.sql, location=jrt:/java.sql]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module java.sql.rowset, location=jrt:/java.sql.rowset]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module java.transaction.xa, location=jrt:/java.transaction.xa]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module java.xml, location=jrt:/java.xml]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module java.xml.crypto, location=jrt:/java.xml.crypto]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module jdk.accessibility, location=jrt:/jdk.accessibility]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module jdk.attach, location=jrt:/jdk.attach]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module jdk.charsets, location=jrt:/jdk.charsets]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module jdk.compiler, location=jrt:/jdk.compiler]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module jdk.crypto.cryptoki, location=jrt:/jdk.crypto.cryptoki]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module jdk.crypto.ec, location=jrt:/jdk.crypto.ec]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module jdk.dynalink, location=jrt:/jdk.dynalink]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module jdk.editpad, location=jrt:/jdk.editpad]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module jdk.httpserver, location=jrt:/jdk.httpserver]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module jdk.internal.ed, location=jrt:/jdk.internal.ed]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module jdk.internal.jvmstat, location=jrt:/jdk.internal.jvmstat]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module jdk.internal.le, location=jrt:/jdk.internal.le]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module jdk.internal.opt, location=jrt:/jdk.internal.opt]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module jdk.jartool, location=jrt:/jdk.jartool]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module jdk.javadoc, location=jrt:/jdk.javadoc]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module jdk.jconsole, location=jrt:/jdk.jconsole]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module jdk.jdeps, location=jrt:/jdk.jdeps]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module jdk.jdi, location=jrt:/jdk.jdi]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module jdk.jdwp.agent, location=jrt:/jdk.jdwp.agent]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module jdk.jfr, location=jrt:/jdk.jfr]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module jdk.jlink, location=jrt:/jdk.jlink]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module jdk.jpackage, location=jrt:/jdk.jpackage]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module jdk.jshell, location=jrt:/jdk.jshell]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module jdk.jsobject, location=jrt:/jdk.jsobject]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module jdk.jstatd, location=jrt:/jdk.jstatd]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module jdk.localedata, location=jrt:/jdk.localedata]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module jdk.management, location=jrt:/jdk.management]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module jdk.management.agent, location=jrt:/jdk.management.agent]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module jdk.management.jfr, location=jrt:/jdk.management.jfr]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module jdk.naming.dns, location=jrt:/jdk.naming.dns]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module jdk.naming.rmi, location=jrt:/jdk.naming.rmi]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module jdk.net, location=jrt:/jdk.net]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module jdk.nio.mapmode, location=jrt:/jdk.nio.mapmode]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module jdk.random, location=jrt:/jdk.random]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module jdk.sctp, location=jrt:/jdk.sctp]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module jdk.security.auth, location=jrt:/jdk.security.auth]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module jdk.security.jgss, location=jrt:/jdk.security.jgss]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module jdk.unsupported, location=jrt:/jdk.unsupported]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module jdk.unsupported.desktop, location=jrt:/jdk.unsupported.desktop]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module jdk.xml.dom, location=jrt:/jdk.xml.dom]
2023-09-23T22:03:45.541-0400	ClassGraph	-- [module jdk.zipfs, location=jrt:/jdk.zipfs]
2023-09-23T22:03:45.541-0400	ClassGraph	Scanning classpath elements (took 0.001355 sec)
2023-09-23T22:03:45.543-0400	ClassGraph	Masking classfiles (took 0.000031 sec)
2023-09-23T22:03:45.543-0400	ClassGraph	Scanning classfiles (took 0.000025 sec)
2023-09-23T22:03:45.543-0400	ClassGraph	Linking related classfiles (took 0.000012 sec)
2023-09-23T22:03:45.544-0400	ClassGraph	Total time: 0.003 sec
@lukehutch
Copy link
Member

Hi, sorry this took me forever to get to!

I think I fixed the problem, but please take a look at my changes and let me know if I understood properly what you were explaining...

lukehutch added a commit that referenced this issue Mar 6, 2024
@mgroth0
Copy link
Author

mgroth0 commented Mar 14, 2024

Hey, thank you for looking into it! I realize my original issue was not worded the best, I appreciate you taking the time to sort through it.

I am also trying to refresh my memory and understand the changes you made. One thing I noticed which confused me is this:

https://github.com/classgraph/classgraph/blob/287824f1ed34aa1ed133a9f77003294787815aba/src/main/java/nonapi/io/github/classgraph/classpath/ClasspathFinder.java#L140C2-L146C22

Here it seems like scanSpec.enableSystemJarsAndModules is set to true conditionally on whether or not classpathFinderLog is null or not. I think this is a mistake, because why would the log configuration have any side effect on the output of the scan?

@mgroth0
Copy link
Author

mgroth0 commented Mar 14, 2024

So assuming setting enableSystemJarsAndModules conditional on some log-related configuration was a mistake, these are the changes in behavior I see that you made:

  1. enableSystemJarsAndModules is no longer enabled for the AppClassLoader. Now, it is only enabled for the PlatformClassLoader .

This change seems to make sense to me. The AppClassLoader is for the regular user-defined classpath, not for JDK platform classes.

  1. forceScanJavaClassPath no longer cares about what ignoreParentClassLoaders is set to.

This also makes sense. If the user specifes the classloader to be scanned to be the AppClassLoader but also specifices to ignore parent classloaders, that would mean that the user expects the Platform classloader and the Boostrap classloader to be ignored. The classpath is loaded by the AppClassLoader, which would not be ignored in this case since only parents of it are ignored, so it makes sense for it the classpath to be scanned in this case.

Though I am curious about one thing which could be another issue. If only one classloader is specified, and it is the PlatformClassLoader, why should this be causing forceScanJavaClassPath to be set to true? If the only classloader set is the PlatformClassLoader, shouldn't that only scan platform classes, since classpath classes are loaded by the AppClassLoader? This might still be an issue.

@lukehutch
Copy link
Member

Here it seems like scanSpec.enableSystemJarsAndModules is set to true conditionally on whether or not classpathFinderLog is null or not. I think this is a mistake, because why would the log configuration have any side effect on the output of the scan?

Oops, good catch! Thanks, fixed.

@lukehutch
Copy link
Member

Correct on your points 1 and 2. I hope this doesn't break things for other users, but I think the changes make sense.

To be honest though I left the Java world about 18 months ago, and I'm getting rusty on this stuff now, so I'll rely on your judgment as to whether these are appropriate changes!

Though I am curious about one thing which could be another issue. If only one classloader is specified, and it is the PlatformClassLoader, why should this be causing forceScanJavaClassPath to be set to true?

Because in JDK 9+, it is impossible to get non-module (traditional) classpath entries from the classloaders. The classes are encapsulated against reflection, and they don't expose the URLs of the traditional classpath, because they don't extend URLClassLoader. The only hope for finding traditional classpath entries is through java.class.path. The only classes and resources you can get from PlatformClassLoader and AppClassLoader are via the module API, and that API only applies to classes added as actual modules. (In fact it's even impossible to get the location on disk of a module's zipfile via the module API.)

Please check if this now satisfies your expectations, after the fix and the above explanation.

Thanks!

@mgroth0
Copy link
Author

mgroth0 commented Mar 16, 2024

The only classes and resources you can get from PlatformClassLoader and AppClassLoader are via the module API, and that API only applies to classes added as actual modules.

So to put it in other words, Classgraph is just taking the PlatformClassLoader and AppClassLoader as tokens, and if it receives these tokens it gets all of the info from the module API? And the module API does not distinguish between platform and classpath classes, or at least you are not distinguishing platform and classpath classes in your usage of the module API? And the PlatformClassLoader and AppClassLoader are never actually used?

If this is true, then I feel caught up and I think that this can be closed!

If we were to design a Classgraph 5.0 API, I might suggest a (breaking) change that would just clarify all of this directly in the API. I think I would throw an exception if the PlatformClassLoader and AppClassLoader are added, to avoid any possible confusion that they are actually used and would just rely on special flags for loading stuff from the module API (seems like these flags are already there, like enableSystemJarsAndModules, so maybe the only change would be to throw exceptions if PlatformClassLoader or AppClassLoader are added).

But for now, I am content. Thank you, and congratulations for escaping Java :)

@lukehutch
Copy link
Member

But for now, I am content. Thank you, and congratulations for escaping Java :)

Hah, thanks -- I found a new home in Dart -- and Dart is so much better than Java that I never want to touch Java again if I can avoid it! At some point I'm going to try to find a new home for ClassGraph, because I won't be able to maintain it forever.

So to put it in other words, Classgraph is just taking the PlatformClassLoader and AppClassLoader as tokens, and if it receives these tokens it gets all of the info from the module API?

Well most of the time, nobody is trying to override the classloader with a system classloader (either of these two). They have a custom classloader that they want to scan. That's what the API is for: for throwing away all the environment classloaders, and scanning another classloader that is not part of the runtime environment (e.g. you could instantiate your own URLClassLoader subclass, to load your own classes, and you may want to scan the URLs that were passed in to that classloader).

If one of the two JDK9+ classloaders is detected in the runtime environment, and if the environment classloaders are not overridden (as you are trying to do), then ClassGraph will enable module scanning, through the module API, unless it has been manually disabled.

But yes, basically there is no way to scan anything at all in PlatformClassLoader or AppClassLoader except through the module API, even though both of these classloaders are able to also scan java.class.path.

Actually because of strong encapsulation in JDK 9+ (which started to be enforced in JDK 16), I wrote Narcissus:

https://github.com/toolfactory/narcissus

This uses the JNI API to override all Java security. You can actually use this during scanning, if you have any classloader that does not expose the classpath publicly, but has a classpath in some private field, and you're running on JDK 16+:

https://github.com/classgraph/classgraph?tab=readme-ov-file#running-on-jdk-16

This could probably be used to read the classpath from AppClassLoader and PlatformClassLoader, but I didn't bother trying to figure out which private field this was stored in for these classloaders, because I'm pretty sure they only use java.class.path, and that can be read much more simply.

As far as the module scanning API, it is possible that one or both of these system classloaders can contain module layers that are not visible to the running program, and maybe you would want to scan these too, but it would be far too complex (and not future-proof) to try to get around module visibility limitations using Narcissus-based reflection. So I didn't bother doing this either, and the module scanner can only scan modules that are in module layers that are visible to the running code.

Anyway, these are the complex reasons for the logic surrounding these classloaders...!

If we were to design a Classgraph 5.0 API, I might suggest a (breaking) change that would just clarify all of this directly in the API.

Half the open bugs are TODO items for Classgraph 5.0, so I'll keep this bug open for now, but I'll change the subject line to reflect this.

But for now, I am content.

Great, thanks for verifying. I pushed out a bugfix release for the bug you noticed, as 4.8.169. Thanks for your eagle-eyed checking over the code changes!

@lukehutch lukehutch changed the title Unexpected behavior from overrideClassLoaders(ClassLoader.getSystemClassLoader()) + ignoreParentClassLoaders() Don't allow PlatformClassLoader or AppClassLoader as override classloaders Mar 16, 2024
@lukehutch
Copy link
Member

So, note to self, this is what this issue is now about:

If we were to design a Classgraph 5.0 API, I might suggest a (breaking) change that would just clarify all of this directly in the API. I think I would throw an exception if the PlatformClassLoader and AppClassLoader are added, to avoid any possible confusion that they are actually used and would just rely on special flags for loading stuff from the module API (seems like these flags are already there, like enableSystemJarsAndModules, so maybe the only change would be to throw exceptions if PlatformClassLoader or AppClassLoader are added).

However, I might take this further, and actually require the user to specify exactly which classloaders they want to scan, and which classpath specification mechanisms (classpath or module API), otherwise ClassGraph should not scan anything by default. That way there is no confusion over what will be scanned.

@mgroth0
Copy link
Author

mgroth0 commented Mar 16, 2024

Hah, thanks -- I found a new home in Dart -- and Dart is so much better than Java that I never want to touch Java again if I can avoid it!

Interesting! I know nothing about Dart. I purely use Kotlin now, so I've escaped Java too but I still find the JVM and java libraries and frameworks useful.

Anyway, these are the complex reasons for the logic surrounding these classloaders...!

I have to admit I don't 100% understand the complexities of this, but I really appreciate that you took the time to write it. If I ever have any confusion about this behavior of Classgraph I can come back here and review this.

Narcissus looks cool. There have been one or two times I had to access an inernal class (like jdk.internal.misc.VM), and this required me to set up this whole annoying --add-opens argument . Maybe Narcissus would allow me access VM in a more convenient way, so I should check it out sometime.

However, I might take this further, and actually require the user to specify exactly which classloaders they want to scan, and which classpath specification mechanisms (classpath or module API), otherwise ClassGraph should not scan anything by default. That way there is no confusion over what will be scanned.

This sounds great! I appreciate that you're considering this. I think users would benefit a lot from these changes because it would greatly clarify the scanning mechanisms being used. I know I would prefer a more clear API (even if it increased the number of lines of code it took do the same thing, I would prefer clarity.)

@lukehutch
Copy link
Member

Well Narcissus is an abominable hack, it's only there if you really need it, and Oracle could close this loophole at any time. But frankly at this point I have enough scars from Java that I don't really care what happens in the Java world in the future! 😁

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