如何设置我的类加载器的JVM的ClassLoader加载所有类(JAR类含)?(How to set

2019-10-16 14:48发布

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

所以,我认为我应该创建一个定制ClassLoader! 通过覆盖类加载器,我可以看看每一个,因为它加载正在使用的类。

我开始了一下周围玩的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. 正在创建一个定制的ClassLoader的正确途径顶部描述的问题?

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

  3. 这是我的理解是通过“委托系统”,父类加载器得到第一次尝试加载类; 这可能是我的ClassLoader没有加载任何东西的原因。 如果我是正确的,怎么我禁用此功能? 如何让我的类加载器做加载?

Answer 1:

该仪器的API将是一个天生适合什么,我认为你正在试图做的

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

它可以让你拦截类,因为它们是在JVM加载 - 通常对它们进行修改,但你给出的字节数组,所以我看不出有什么理由,你为什么不能没有真正修改进行任何必要的分析发挥。

这将帮助您分析类被加载之前。 我不是什么是你正在努力实现完全清楚,但如果你能分析类后,他们被加载,那么你可以简单地打开和分析类路径上的所有jar文件的内容。



文章来源: How to set my ClassLoader as the JVM's ClassLoader for loading ALL classes (jar classes included)?