I am working on an application that has a plugin framework. It uses a custom classloader to load plugins from encrypted jar files. Initially I painted myself into using the custom classloader as a bootstrapped system classloader. In this way it worked, but there are some drawbacks in using a custom system classloader.
I am trying to rework so that the custom classloader is only utilized to load the plugins. The plugins are hierarchical in nature and therefore need the same class context. To that end, the plugin classloader CustomClassloader
is a singleton which extends ClassLoader
and has the parent classloader set to the SystemClassloader (and delegates classloading to parent as is the normal pattern).
This seems to be working well EXCEPT in a particular case where I need to create a lambda function that allows the generic ('reflective') setting of a POJO boolean field that is defined within the plugin.
lambda_set
creation (defined within an application jar that is loaded by the system classloader):
private BiConsumer<POJO_Interface, Object> lambda_set = null;
Class[] parameter = new Class[1];
parameter[0] = field_clazz; // in this case it is boolean.class
set_method = pojo_class.getMethod(setter.trim(), parameter); // setter method name
set_method.setAccessible(true);
MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodHandle target = lookup.unreflect(set_method);
MethodType func = target.type();
MethodType func1 = func.changeParameterType(0, Object.class);
if(func.parameterCount() >= 2)
func1 = func1.changeParameterType(1, Object.class);
CallSite site = LambdaMetafactory.metafactory(lookup, "accept",
MethodType.methodType(BiConsumer.class), func1, target, func);
MethodHandle factory = site.getTarget();
lambda_set = (BiConsumer) factory.invoke();
When I call lambda_set.accept(pojo, value);
I get a ClassNotFoundException
for the POJOs superclass. Each POJO extends it's own parent abstract class that implements the POJO_Interface
and contains its fields and getters/setters. This same function works fine when everything is loaded from the custom bootstrap classloader. I've verified that it is trying to load the POJO's parent class in the System classloader exclusively instead of the CustomClassloader
which is wrong.
I've verified that the pojo.getClass().getClassLoader() == pojo_class.getClassLoader() == CustomClassloader.class
However, the lambda_set.getClass().getClassLoader() == jdk.internal.loader.ClassLoaders$AppClassLoader
. I'm not sure if this is the problem.
This behavior is the same in JDK8-JDK14.
Is there a way that I can make the lambda_set
utilize my CustomClassloader
when it needs to load a class? Any other insights would be appreciated!
Aucun commentaire:
Enregistrer un commentaire