当前位置: 首页 > 知识库问答 >
问题:

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

司寇飞航
2023-03-14

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

代理可以很好地处理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. 在应用程序内部,将类的实例分配给它的接口,并调用它的检测方法。
  4. 使用-javaagent运行应用程序进行检查。

共有1个答案

鲜于允晨
2023-03-14

我假设您的类没有正确检测,因为您正在调用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 类加载与自定义类加载器详解,包括了java 类加载与自定义类加载器详解的使用技巧和注意事项,需要的朋友参考一下 类加载 所有类加载器,都是ClassLoader的子类。 类加载器永远以.class运行的目录为准。 读取classpath根目录下的文件有以下几种方式: 1 在Java项目中可以通过以下方式获取classspath下的文件: 在Tomcat中tomcat又声明了

  • 我一直在Java玩简单的自定义类加载器,到目前为止,对于非模块相关的类来说,一切都按照预期工作。但是,我似乎找不到任何方法来使用我的类加载器从模块加载类,即使与模块相关的方法已经被重载。我尝试做的是从模块“HelloModularWorld”加载一个类,并运行它的main。然而,当我指定包所在的目录时,它将“正常”加载,并报告为在未命名模块中。我错过了什么? 类加载器只是从文件系统的其他地方加载类

  • 问题内容: 我一直在尝试建立一个自定义的类加载器,该类加载器将拦截类以打印出哪些类正在加载到应用程序中。类加载器看起来像这样 它只是吐出它加载的所有类的名称。但是,当我尝试运行一些代码时, 通过 它打印出来 这似乎很奇怪。这不是一个简单的类,它取决于程序包中的许多其他类。这些类显然正在加载中,因为d python代码能够执行操作并读取我的文件。但是,由于某些原因,那些类并未由load的类加载器加载

  • 问题内容: 出于调试原因和好奇心,我希望列出所有加载到特定类加载器的类。 鉴于类加载器的大多数方法都受到保护,实现我想要的最佳方法是什么? 谢谢! 问题答案: 可以做你想要的。 根据文档: 返回所有类的数组,这些类的加载程序是初始加载程序。 我不确定“启动加载程序”是什么意思。如果这样不能给出正确的结果,请尝试使用该方法并通过ClassLoader手动进行过滤。 如何获得的实例 只有代理JAR(与

  • 问题内容: 我有一个Java类,它在启动时基于javassist类加载器创建自定义类加载器,然后运行实际的程序类。我收到以下错误: 该问题与以下事实有关:一个对象是由原始类加载器创建的,而另一个是由自定义类创建的。 有没有办法解决此错误? 在此先感谢 Avner 问题答案: 请尝试将-Dlog4j.ignoreTCL =true设置为希望有帮助。关于log4j的类似问题

  • 本文向大家介绍浅谈Java自定义类加载器及JVM自带的类加载器之间的交互关系,包括了浅谈Java自定义类加载器及JVM自带的类加载器之间的交互关系的使用技巧和注意事项,需要的朋友参考一下 JVM自带的类加载器: 其关系如下: 其中,类加载器在加载类的时候是使用了所谓的“父委托”机制。其中,除了根类加载器以外,其他的类加载器都有且只有一个父类加载器。 关于父委托机制的说明: 当生成 一个自定义的类加