父类最后一个类加载器来解决Java类路径地狱?
我有一个项目,它使用两个版本的bouncyCastle jars bcprov-jdk15和bcprov-jdk16。jvm加载旧版本,但我编写了一个功能,需要运行新版本。我试图通过使用自定义类加载器来解决这个类路径地狱。在一些Google搜索之后,在一些以前的Stackoverflow答案的帮助下,我编写了下面的Parent Last Class loader,以便在委托给父类装入器之前从较新的jar装入类父类最后一个类加载器来解决Java类路径地狱?,java,classpath,classloader,bouncycastle,Java,Classpath,Classloader,Bouncycastle,我有一个项目,它使用两个版本的bouncyCastle jars bcprov-jdk15和bcprov-jdk16。jvm加载旧版本,但我编写了一个功能,需要运行新版本。我试图通过使用自定义类加载器来解决这个类路径地狱。在一些Google搜索之后,在一些以前的Stackoverflow答案的帮助下,我编写了下面的Parent Last Class loader,以便在委托给父类装入器之前从较新的jar装入类 public class ParentLastClassLoader extends
public class ParentLastClassLoader extends ClassLoader {
private String jarFile; //Path to the jar file
private Hashtable classes = new Hashtable(); //used to cache already defined classes
public ParentLastClassLoader(ClassLoader parent, String path)
{
super(parent);
this.jarFile = path;
}
@Override
public Class<?> findClass(String name) throws ClassNotFoundException
{
System.out.println("Trying to find");
throw new ClassNotFoundException();
}
@Override
protected synchronized Class<?> loadClass(String className, boolean resolve) throws ClassNotFoundException
{
System.out.println("Trying to load");
try
{
System.out.println("Loading class in Child : " + className);
byte classByte[];
Class result = null;
//checks in cached classes
result = (Class) classes.get(className);
if (result != null) {
return result;
}
try {
JarFile jar = new JarFile(jarFile);
JarEntry entry = jar.getJarEntry(className + ".class");
InputStream is = jar.getInputStream(entry);
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
int nextValue = is.read();
while (-1 != nextValue) {
byteStream.write(nextValue);
nextValue = is.read();
}
classByte = byteStream.toByteArray();
result = defineClass(className, classByte, 0, classByte.length, null);
classes.put(className, result);
return result;
} catch (Exception e) {
throw new ClassNotFoundException(className + "Not found", e);
}
}
catch( ClassNotFoundException e ){
System.out.println("Delegating to parent : " + className);
// didn't find it, try the parent
return super.loadClass(className, resolve);
}
}
}
Jvm仍然使用从旧版本加载的类。如何使JVM在运行该功能时从我的类加载器加载类,并在该功能未运行时使用旧jar中已加载的旧类
编辑:
即使将自定义类加载器设置为feature Main类的Main方法中的线程上下文类加载器,问题仍然存在
Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
好的,您创建了自己的类加载器,然后使用它加载了一个类。问题是-线程类加载器如何知道这一点?
因此,您必须使用一些类加载器加载该类,然后将该类加载器设置为线程上下文类加载器。我设法解决了这个问题。修改了ParentLastClassLoader的代码,以获得该功能所需的所有Jarfile路径的数组。因此,当加载一个类时,将搜索该功能所需的所有JAR文件以查找.class文件。如果找不到类文件,则将其委托给父级
private class ParentLastClassLoader extends ClassLoader {
private String[] jarFiles; //Paths to the jar files
private Hashtable classes = new Hashtable(); //used to cache already defined classes
public ParentLastClassLoader(ClassLoader parent, String[] paths)
{
super(parent);
this.jarFiles = paths;
}
@Override
public Class<?> findClass(String name) throws ClassNotFoundException
{
System.out.println("Trying to find");
throw new ClassNotFoundException();
}
@Override
protected synchronized Class<?> loadClass(String className, boolean resolve) throws ClassNotFoundException
{
System.out.println("Trying to load");
try
{
System.out.println("Loading class in Child : " + className);
byte classByte[];
Class result = null;
//checks in cached classes
result = (Class) classes.get(className);
if (result != null) {
return result;
}
for(String jarFile: jarFiles){
try {
JarFile jar = new JarFile(jarFile);
JarEntry entry = jar.getJarEntry(className.replace(".","/") + ".class");
InputStream is = jar.getInputStream(entry);
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
int nextValue = is.read();
while (-1 != nextValue) {
byteStream.write(nextValue);
nextValue = is.read();
}
classByte = byteStream.toByteArray();
result = defineClass(className, classByte, 0, classByte.length, null);
classes.put(className, result);
} catch (Exception e) {
continue;
}
}
result = (Class) classes.get(className);
if (result != null) {
return result;
}
else{
throw new ClassNotFoundException("Not found "+ className);
}
}
catch( ClassNotFoundException e ){
System.out.println("Delegating to parent : " + className);
// didn't find it, try the parent
return super.loadClass(className, resolve);
}
}
}
一旦ParentLastClassLoader被实例化,将加载MainClassofFeature,并调用其MainMethod。我还没有完全理解这是如何工作的,或者为什么需要它,但这是目前我能够自动链接jar中其他类的唯一方法。
private class ParentLastClassLoader extends ClassLoader {
private String[] jarFiles; //Paths to the jar files
private Hashtable classes = new Hashtable(); //used to cache already defined classes
public ParentLastClassLoader(ClassLoader parent, String[] paths)
{
super(parent);
this.jarFiles = paths;
}
@Override
public Class<?> findClass(String name) throws ClassNotFoundException
{
System.out.println("Trying to find");
throw new ClassNotFoundException();
}
@Override
protected synchronized Class<?> loadClass(String className, boolean resolve) throws ClassNotFoundException
{
System.out.println("Trying to load");
try
{
System.out.println("Loading class in Child : " + className);
byte classByte[];
Class result = null;
//checks in cached classes
result = (Class) classes.get(className);
if (result != null) {
return result;
}
for(String jarFile: jarFiles){
try {
JarFile jar = new JarFile(jarFile);
JarEntry entry = jar.getJarEntry(className.replace(".","/") + ".class");
InputStream is = jar.getInputStream(entry);
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
int nextValue = is.read();
while (-1 != nextValue) {
byteStream.write(nextValue);
nextValue = is.read();
}
classByte = byteStream.toByteArray();
result = defineClass(className, classByte, 0, classByte.length, null);
classes.put(className, result);
} catch (Exception e) {
continue;
}
}
result = (Class) classes.get(className);
if (result != null) {
return result;
}
else{
throw new ClassNotFoundException("Not found "+ className);
}
}
catch( ClassNotFoundException e ){
System.out.println("Delegating to parent : " + className);
// didn't find it, try the parent
return super.loadClass(className, resolve);
}
}
}
ClassLoader loader = new ParentLastClassLoader(Thread.currentThread().getContextClassLoader(), paths);