如何将我的类加载器设置为JVM的类加载器,以加载所有类(包括jar类)?



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

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

我开始玩一些ClassLoaders。这是我所做的:(我从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 + "ntshould be equal ton" + 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 对所有线程使用 MY 类加载器?(不仅仅是第一个线程,我希望创建的每个新线程都自动使用我的类加载器)

  3. 我的
  4. 理解是,通过"委托系统",父类加载器可以第一次尝试加载类;这可能是我的类加载器没有加载任何内容的原因。如果我是对的,如何禁用此功能?如何让我的类加载器进行加载?

检测 api 非常适合我认为您要做的事情

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

它允许您在 JVM 加载类时拦截类 - 通常是为了修改它们,但你会得到要使用的字节数组,所以我看不出为什么你不能在不实际修改的情况下执行任何所需的分析。

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

最新更新