gpt4 book ai didi

java - 如何检测自定义类加载器加载的类?

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:14:49 24 4
gpt4 key购买 nike

我试图修改几个类的字节码,它们的打包 jar 文件不在类路径中 - 它们在运行时由自定义 ClassLoader 加载给定 URL。我尝试将 java agentClassFileTransformer 一起使用,希望拦截这些类但失败了。类加载器是遗留项目的一部分,因此我无法直接对其进行更改。

代理在“本地”由 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 实例中;我是仪器/类加载的新手,对它们的机制还不是很清楚。有什么帮助吗?谢谢。

为简单起见:

  1. 在应用程序内部创建一个自定义 URLClassLoader,它会在运行时加载文件系统中其他位置的一些 jar 文件。
  2. 实现一个 java 代理,转换由您的类加载器加载的类,替换其中一个方法的主体或其他内容。
  3. 在应用程序内部,将一个类的实例分配给它的接口(interface)并调用它的检测方法。
  4. 使用 -javaagent 运行应用程序进行检查。

最佳答案

我假设您的类没有正确检测,因为您正在调用 ClassPool.getDefault(),它不包括对您的自定义类加载器可见但仅对系统类加载器可见的类文件。您永远不会注册 classfileBuffer 类文件。

作为替代方案,您可以试试 Byte Buddy它提供了对检测 API 的更容易访问:

new AgentBuilder.Default()
.type(named("com.example.services.TargetService"))
.transform((builder, type, loader) -> {
builder.method(named("verify")).intercept(FixedValue.of(true));
}).installOn(instrumentation);

可以从agentmainpremain 方法调用上述代理。您还可以禁用类文件格式更改并重新定义现有类,以防类在附件期间已经(可能)加载。

关于java - 如何检测自定义类加载器加载的类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37542592/

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