我试图修改几个类的字节代码,这些类的打包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实例中;我是一个新的仪器/类加载,仍然不是很清楚他们的机制。有人帮忙吗?多谢了。
为了简单起见:
我假设您的类没有正确检测,因为您正在调用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);
可以从agentmain
或premain
方法调用上述代理。您还可以禁用类文件格式更改,并重新定义现有类,以防类已经(可能)在附件期间加载。
本文向大家介绍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自带的类加载器: 其关系如下: 其中,类加载器在加载类的时候是使用了所谓的“父委托”机制。其中,除了根类加载器以外,其他的类加载器都有且只有一个父类加载器。 关于父委托机制的说明: 当生成 一个自定义的类加