classgraph: FD leak causes invalid ScanResults when run on large classpath

After upgrading Atomix to ClassGraph i’m seeing that it fails to load public inner classes yet I haven’t changed anything wrt class loaders…

java.lang.IllegalArgumentException: Could not load class io.atomix.protocols.backup.MultiPrimaryProtocol$Type

	at io.github.classgraph.ScanResult.loadClass(ScanResult.java:720)
	at io.github.classgraph.ScanResultObject.loadClass(ScanResultObject.java:145)
	at io.github.classgraph.ClassInfo.loadClass(ClassInfo.java:1691)
	at io.atomix.core.impl.ClasspathScanningAtomixRegistry.lambda$new$0(ClasspathScanningAtomixRegistry.java:56)
	at java.util.ArrayList.forEach(ArrayList.java:1249)
	at io.atomix.core.impl.ClasspathScanningAtomixRegistry.<init>(ClasspathScanningAtomixRegistry.java:52)
	at io.atomix.core.impl.ClasspathScanningAtomixRegistry.<init>(ClasspathScanningAtomixRegistry.java:41)
	at io.atomix.core.AtomixRegistry.registry(AtomixRegistry.java:49)
	at io.atomix.core.Atomix.builder(Atomix.java:288)
	at io.atomix.core.Atomix.builder(Atomix.java:275)
	at io.atomix.core.AbstractAtomixTest.buildAtomix(AbstractAtomixTest.java:76)
	at io.atomix.core.AbstractAtomixTest.createAtomix(AbstractAtomixTest.java:110)
	at io.atomix.core.AbstractAtomixTest.createAtomix(AbstractAtomixTest.java:103)
	at io.atomix.core.AbstractPrimitiveTest.setupCluster(AbstractPrimitiveTest.java:82)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
	at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.lang.IllegalArgumentException: No classloader was able to load class io.atomix.protocols.backup.MultiPrimaryProtocol$Type
	at io.github.classgraph.ScanResult.loadClass(ScanResult.java:682)
	at io.github.classgraph.ScanResult.loadClass(ScanResult.java:715)
	... 28 more

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 40 (40 by maintainers)

Commits related to this issue

Most upvoted comments

@johnou Great, and yes, you’re absolutely right about that. What was happening is that the inner interface class was being referenced somewhere else on the classpath, and since the class itself had not been scanned (because it couldn’t be, because all the fds were used up), it was created as a placeholder ClassInfo for an “external class” (just as with class references for superclasses that are not in a whitelisted path).

I really appreciate you catching this, and for helping me track down the cause. It was a very serious bug!