I am attempting to get a custom classloader to work with loading random .class
files that could be anywhere on the filesystem. I wrote my class loader to extend ClassLoader
, overrode the findClass()
and loadClass()
methods, and read in the byte stream of the class file. The issue arises when trying to invoke ClassLoader.defineClass()
The exact error I get is:
Exception in thread "main" java.lang.NoClassDefFoundError: Test (wrong name: com/foo/bar/Test)
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:800)
I know that the problem is that the native classloading function doesn't like the fact that Test.class
doesn't live in /someDir/com/foo/bar/
. Is there any way I can make this work? My classloader already has code to check that the defined class conforms to a particular package. I really don't see why the native method would disallow this (other than security, which I don't need in this use case, and event then, let me shoot myself in the foot).
Native class loader, i.e. ClassLoader.defineClass1
, does not know anything about directory structure. It just loads a byte array.
The error message says that the binary name passed as an argument to defineClass
does not match the actual name discovered from the class data bytes. The easiest workaround is to set name=null
when calling defineClass
.
Note: you cannot change a package of a class by simply moving it to a different directory. The package name is embedded in class file data. You have to either recompile sources with proper package
directive or modify class files bytes with bytecode instrumentation framework while loading.