簡體   English   中英

使用自定義 ClassLoader 覆蓋現有的類實現

[英]Using a custom ClassLoader to override existing implementations of classes

首先,我知道以前有人問過這個問題,但是我所見過的解決方案都沒有對我有用!

In order to be able to override existing implementations of classes with new bytecode I want a class loader(set as default) where all calls for any class(excluding java packages like "java.") go through my loadClass/findClass overridden methods. 從那里我可以檢查 static 注冊表,看看是否有針對該 class 的覆蓋。 我願意嘗試以不同的方式做到這一點,但到目前為止,這看起來是最快和最簡單的解決方案。

我的問題是,由於某種原因,即使我將加載程序設置為 VM args 中的默認值( -Djava.system.class.loader=my.package.path.ProxyClassLoader )它會將加載(類的)拋出給父級然后,我假設將類加載器設置為自身。 這意味着現在所有查找或加載類的調用 go 通過父類而不是我的類加載器。

Additionally, i would like to use JUnit to test this, but i couldnt get it to use a custom classloader(Using the JUnit API with the JUnit Engine in gradle) so i just went old school and used a main(where i can modifier vm論據)。

我嘗試過的事情:

  1. 將類加載器設置為線程上下文加載器。
  2. 覆蓋 loadclass 以嘗試不將加載交給父級,這只會導致比解決的問題多得多的問題。
  3. 嘗試進行反射以更改類的類加載器(Java 明確不允許這樣做+這將非常緩慢且不值得)

這是我的類加載器:

public class ProxyClassLoader extends ClassLoader {
    public ProxyClassLoader(ClassLoader parent) {
        super(parent);
        Thread.currentThread().setContextClassLoader(this);

    }

    //Didn't look like i need to override anything so 
    //this is just a simplicity thing for me(i call it through other classes)
    public Class<?> defineClass(byte[] b, String name) {
        return super.defineClass(name, b, 0, b.length, defaultDomain);
    }

    @Override
    protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
        if (ClassManager.hasOverload(name)) return ClassManager.retrieve(name);
        return super.loadClass(name, resolve);

    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        return this.loadClass(name, true);
    }
}

謝謝!

不要完全跳過超級 class 裝載機。 試試這樣的東西?

 @Override protected Class<?> loadClass(String name, boolean resolve) throws 
     ClassNotFoundException {
            if(name belongs to java classes) {
                 return super.loadClass(name, resolve);
            }
            byte[] b = ..// read bytes from your .class files. or use getResourceAsStream(name)
            Class<?> c = defineClass(b, name);
            if(resolve) resolveClass(c);
            return c;
        }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM