gpt4 book ai didi

java - 如何将我的 ClassLoader 设置为 JVM 的 ClassLoader 来加载所有类(包括 jar 类)?

转载 作者:行者123 更新时间:2023-11-30 04:49:21 25 4
gpt4 key购买 nike

我正在编写一个游戏引擎,我需要在其中分析程序中提到的每个类。由于这是一个游戏引擎,因此它将作为 JAR 文件附加到客户的项目中。从该 JAR 文件中,我需要能够扫描客户端正在使用的每个类。

所以我想我应该创建一个自定义的类加载器!通过重写 ClassLoader,我可以查看加载时正在使用的每个类。

我开始尝试使用类加载器。这是我所做的:(我从 JavaWorld 偷了这个类加载器只是为了玩玩它)

public class SimpleClassLoader extends ClassLoader {
private HashMap<String, Class> classes = new HashMap<String, Class>();

public SimpleClassLoader() {
}

/**
* This sample function for reading class implementations reads
* them from the local file system
*/
private byte getClassImplFromDataBase(String className)[] {
System.out.println(" >>>>>> Fetching the implementation of "+className);
byte result[];
try {
FileInputStream fi = new FileInputStream("store\\"+className+".impl");
result = new byte[fi.available()];
fi.read(result);
return result;
} catch (Exception e) {

/*
* If we caught an exception, either the class wasnt found or it
* was unreadable by our process.
*/
return null;
}
}

/**
* This is a simple version for external clients since they
* will always want the class resolved before it is returned
* to them.
*/
public Class loadClass(String className) throws ClassNotFoundException {
return (loadClass(className, true));
}

/**
* This is the required version of loadClass which is called
* both from loadClass above and from the internal function
* FindClassFromClass.
*/
public synchronized Class loadClass(String className, boolean resolveIt)
throws ClassNotFoundException {
Class result;
byte classData[];

System.out.println(className);

System.out.println(" >>>>>> Load class : "+className);

/* Check our local cache of classes */
result = (Class)classes.get(className);
if (result != null) {
System.out.println(" >>>>>> returning cached result.");
return result;
}

/* Check with the primordial class loader */
try {
result = super.findSystemClass(className);
System.out.println(" >>>>>> returning system class (in CLASSPATH).");
return result;
} catch (ClassNotFoundException e) {
System.out.println(" >>>>>> Not a system class.");
}

/* Try to load it from our repository */
classData = getClassImplFromDataBase(className);
if (classData == null) {
throw new ClassNotFoundException();
}

/* Define it (parse the class file) */
result = defineClass(classData, 0, classData.length);
if (result == null) {
throw new ClassFormatError();
}

if (resolveIt) {
resolveClass(result);
}

classes.put(className, result);
System.out.println(" >>>>>> Returning newly loaded class.");
return result;
}
}
<小时/>

然后我决定测试一下:

<小时/>
public class Test
{
public static void main(String args[]) throws ClassNotFoundException
{
SimpleClassLoader s = new SimpleClassLoader();
Thread.currentThread().setContextClassLoader(s);

Foo myfoo = new Foo(); //local class
ArrayList myList = new ArrayList(); //class from JAR file

//both should have been loaded from my SimpleClassLoader
System.out.println(s + "\n\tshould be equal to\n" + myfoo.getClass().getClassLoader());
System.out.println("\tand also to: \n" + myList.getClass().getClassLoader());

/*
OUTPUT:

SimpleClassLoader@57fee6fc
should be equal to
sun.misc.Launcher$AppClassLoader@51f12c4e
and also to:
null

***

bizarre results: why are ArrayList and Foo not being loaded by my classloader?

*/


}
}
  1. 创建自定义类加载器是解决顶部描述的问题的正确方法吗?

  2. 为什么要调用系统类加载器?如何强制 JVM 对所有线程使用我的类加载器?(不仅仅是第一个线程,我希望创建的每个新线程都自动使用我的类加载器)

  3. 据我了解,通过“委托(delegate)系统”,父类加载器首先尝试加载类;这可能是我的类加载器未加载任何内容的原因。如果我是对的,如何禁用此功能?如何让我的类加载器进行加载?

最佳答案

仪表 API 非常适合我认为您想要做的事情

http://docs.oracle.com/javase/6/docs/api/java/lang/instrument/Instrumentation.html

它可以让您在 JVM 加载类时拦截它们 - 通常是为了修改它们,但您会获得要使用的字节数组,因此我认为您没有理由在不实际修改的情况下无法执行任何所需的分析。

这可以让您在加载类之前对其进行分析。我不完全清楚您想要实现的目标是什么,但是如果您可以在加载类后对其进行分析,那么您可以简单地打开并解析类路径上所有 jar 的内容。

关于java - 如何将我的 ClassLoader 设置为 JVM 的 ClassLoader 来加载所有类(包括 jar 类)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10197080/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com