cancel
Showing results for 
Search instead for 
Did you mean: 

ReflectUtil.loadClass() and custom classloader

pgadecki
Champ in-the-making
Champ in-the-making
I'm implementing custom classloader which loads classes from BAR archives and I'm wondering why it is not directly called in ReflectUtil.loadClass()

public static Class<?> loadClass(String className) {
   Class<?> clazz = null;
   ClassLoader classLoader = getCustomClassLoader();
  
   // First exception in chain of classloaders will be used as cause when no class is found in any of them
   Throwable throwable = null;
  
   if(classLoader != null) {
     try {
       LOG.finest("Trying to load class with custom classloader: " + className);
            clazz = Class.forName(className, true, classLoader);
     } catch(Throwable t) {
       throwable = t;
     }
   }


Is there any particular reason to load class using custom classloader in this way:
clazz = Class.forName(className, true, classLoader);
instead of directly calling classloader method:
clazz = classLoader.loadClass(className);
?

My goal is to have possibility to load two versions of the same class during runtime depending on deployment's id during runtime.
It seems that call with Class.forName() my classloader is not called but some cached class is loaded which is not what I (and probably other custom classloader developers) want to achieve.
17 REPLIES 17

oefimov
Champ in-the-making
Champ in-the-making
Joram, I've looked through the ReflectUtil change history – Class.forName has been used since the first version, OSGI changes (commit 1 and commit 2) only added fallback strategy (custom cl -> tccl -> local cl).

I'm not an expert in OSGI, but I believe this change won't make any unforeseen consequences. On the other hand, I understand your adherence to conservative code changes.

Maybe it's possible to add configuration option to support both behaviours? E.g.:
1. boolean property useClassForNameClassLoading in class org.activiti.engine.ProcessEngineConfiguration set to true by default
2. System property org.activiti.engine.useClassForNameClassLoading with the same semantics

I can provide pull request if you approve one of these options.

jbarrez
Star Contributor
Star Contributor
Option 1 is the typical way of doing it in Activiti.

If you would create a pull request, I would most certainly be happy to review it!

redguy1
Champ in-the-making
Champ in-the-making
Any progress on this? I am also interested in calling classloader rather than Class.forName with its caching…

oefimov
Champ in-the-making
Champ in-the-making
I haven't made a pull request yet – probably in a week or two I'll come up with it.

oefimov
Champ in-the-making
Champ in-the-making
Hello Joram,

I've thought about the two options and saw the following problem with the option 1:
I need the configurable parameter in the static context of ReflectUtil, and it will be available only in non-static context of ProcessEngineConfiguration instance.

Could you please suggest smth? Is it acceptable to implement option 2 in Activiti?

Regards,
Oleg.

jbarrez
Star Contributor
Star Contributor
good point. There is a way though, the ProcessEngineConfiguration is set in a static threadlocal, see org.activiti.engine.impl.context.Context. So in theory you can access the configuration through there.

oefimov
Champ in-the-making
Champ in-the-making

oefimov
Champ in-the-making
Champ in-the-making
TWIMC: bundled in 5.17.0, thanks to Activiti team.