• 周二. 7 月 16th, 2024

5G编程聚合网

5G时代下一个聚合的编程学习网

热门标签

Java ~ dynamically loads ~ Tomcat model through classloader

King Wang

1 月 4, 2022

In the process of non WEB project (Springboot) In development , Use classLoader Load dynamically jar, And using the interface for strong type conversion is no problem , They use JVM Under the URLClassLoader To implement , And on the basis of tomcat When you use it in your container , There’s a problem with types that can’t be found , Here’s why :

tomcat There’s a man named webApp It loads first WEB-INF/classes After loading WEB-INF/lib, But its father loader is its common loader ,comon The parent loader is system loader ( and JVM The Application Loader of the application is similar in function , But other things are specified tomcat Loading under Directory , You can look at the English documents on the official website ), But the loader in the source code is URLClassLoader Subclasses of , and URLClassLoader Default parent load tomcat Next is its system The loader is so designed and tomcat Of

Configure the , The default is inaction false, It will be entrusted directly to tomcat Of system Loader loading system Delegate to the top Bootstrap loader ( Is almost JVM The combination of the start loader and the extended loader ), But anyway , The project in tomcat Custom or URLClassLoader Loading the default parent loader will not be tomcat Of webApp The loader is system loader , Or custom loaders or URLClassLoader and tomcat Of webApp The loader has no relationship , So when dynamically creating a class, it will definitely report when designing other classes CNF abnormal .

Reference resources

https://blog.csdn.net/chenleixing/article/details/50042795
https://blog.csdn.net/chenleixing/article/details/47121661
http://tomcat.apache.org/tomcat-7.0-doc/class-loader-howto.html

Tomcat ClassLoader

1

resolvent

One The solution is to get the current class first Class, Then get the loader of the current class , In custom loaders or URLClassLoader Loaders are specified as their parent when they are created , In this way, the problem will be solved easily , Maybe we don’t encounter this problem when we write a simple example , Because we were URLClassLoader Or the parent loader of a custom loader is JVM The third loader of is the application load , It’s dedicated to loading classpath The following or specified class or jar Of , According to the parental delegation model , You’ll definitely find the class that introduced the path or jar Of .

Two Use Class.forName() To dynamically load the specified class , There would be no such problem , Because this way, on the one hand, is able to initialize the static things of the class , And then it’s important , Is to use the loader that loads the current class to load the class you specify , So you’re here tomcat That’s it webApp Loaders , It’s definitely not going to happen again , It may be found directly from the cache .

Dynamic loading code

 URL url = new URL(packageUrl);
// IDEA Debug with java Runtime ClassLoader Is different , So we need to use the current environment ClassLoader
ClassLoader loader = new URLClassLoader(new URL[]{url}, clazz.getClassLoader()) {
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
try {
String fileName = name.substring(name.lastIndexOf(".") + 1) + ".class";
InputStream is = getClass().getResourceAsStream(fileName);
if (is == null) {
return super.loadClass(name);
}
byte[] b = new byte[is.available()];
is.read(b);
return defineClass(name, b, 0, b.length);
} catch (IOException e) {
e.printStackTrace();
throw new ClassNotFoundException(name);
}
}
};

发表回复