我試圖修改其打包jar文件不在類路徑中的幾個類的字節碼 - 它們在運行時通過自定義ClassLoader
加載給定URL。我試圖用java agent
與ClassFileTransformer
希望攔截這些類,但失敗。 classloader是遺留項目的一部分,因此我無法直接對其進行更改。如何儀器類加載自定義類加載器?
該代理對AppClassLoader「本地」加載的類正常工作,但只是忽略由自定義類加載器加載的類。
的CustomClassLoader:
public class CustomClassLoader extends URLClassLoader {
public CustomClassLoader(URL[] urls) {
super(urls, CustomClassLoader.class.getClassLoader());
}
// violates parent-delegation pattern
@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
synchronized (getClassLoadingLock(name)) {
Class<?> clazz = findLoadedClass(name);
if (clazz == null) {
try {
clazz = findClass(name);
} catch (ClassNotFoundException e) {
}
if (clazz == null) {
clazz = getParent().loadClass(name);
}
}
if (resolve) {
resolveClass(clazz);
}
return clazz;
}
}
}
的ClassFileTransformer在我的經紀人使用(用Javassist):
public class MyTransformer implements ClassFileTransformer
{
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException
{
byte[] byteCode = null;
if (className.replace("/", ".").equals("com.example.services.TargetService"))
{
ClassPool cp = ClassPool.getDefault();
CtClass cc;
try
{
cc = cp.get("com.example.services.TargetService");
CtMethod verifyMethod = cc.getDeclaredMethod("verify");
//invalidate the verification process of method : verify
verifyMethod.insertBefore("{return true;}");
byteCode = cc.toBytecode();
cc.detach();
return byteCode;
}
catch (Exception e)
{
e.printStackTrace();
}
}
return byteCode;
}
}
的代理:
public class Agent
{
public static void premain(String agentArgs, Instrumentation inst)
{
inst.addTransformer(new MyTransformer());
}
}
我想出了一個解決方法,通過調用CustomClassLoader本身,調用instrumentation.redifineClasses(),但不知道如何將檢測實例傳遞到CustomClassLoader實例中;我不熟悉儀器/類加載,但仍然不清楚其機制。 有什麼幫助嗎?謝謝。
爲了使簡單:
- 內的應用程序創建而在其他地方,你在運行時的文件系統加載某些jar文件自定義的URLClassLoader。
- 實現一個java代理程序,用於轉換類加載器加載的類,替換其中一個方法的主體或其他東西。
- 在應用程序內部爲其接口分配一個類的實例並調用它的檢測方法。
- 使用-javaagent運行應用程序進行檢查。
你有沒有依賴的簡單代理嘗試過嗎?例如嘗試簡單地調用System.out.println(className);在你的方法轉換中,然後返回classfileBuffer。我試圖用你的CustomClassLoader加載一個類,我在控制檯上看到這個類的名字 –
@NicolasFilotto問題解決了,謝謝,你讓我想起了我用於代理的工具。代理本身得到了類加載事件的通知,但如果外部URL未添加到其類路徑中,則檢測工具無法獲取字節碼。 –