Java插装:防止类引用加载类
大家好,我的社区 我最近发现了Java插装,以及可以用它做什么伟大的事情,所以我决定为自己编写一个小型库,简化其中的一些事情 我有以下方法(简化):Java插装:防止类引用加载类,java,instrumentation,javaagents,java-reflection,Java,Instrumentation,Javaagents,Java Reflection,大家好,我的社区 我最近发现了Java插装,以及可以用它做什么伟大的事情,所以我决定为自己编写一个小型库,简化其中的一些事情 我有以下方法(简化): publicstaticvoideditclass(类clazz){ ... } 它通过工具添加了一个转换器,该工具转换名为clazz.getName()的加载类的字节码 所以在我的premain方法中,我可以说 editClass(Foo.class); 我的问题是,通过对类(.class)的引用来指定该类,该类在添加转换器之前被加载,因此在
publicstaticvoideditclass(类clazz){
...
}
它通过工具添加了一个转换器,该工具转换名为clazz.getName()
的加载类的字节码
所以在我的premain方法中,我可以说
editClass(Foo.class);
我的问题是,通过对类(.class)的引用来指定该类,该类在添加转换器之前被加载,因此在此之后,我必须重新转换该类,这会阻止我添加/删除方法等等
那么,有没有一种方法在使用这个类引用时不加载该类?还是用另一种方法来实现这一点?我知道我可以将类名作为参数传递,但我真的希望使整个库类型安全并使重构更容易
提前谢谢 如果您只想从
premain
调用editClass
方法,并且我们假设Java代理本身不使用该类,因此editClass
调用中的类文本将是唯一的触发器,您可以执行以下操作:
- 提供两种方法,
和editClass(Class clazz)
editClass(String qualifiedName)
- 使用
编写editClass(Class)
方法(或一般的代理类),并享受编译时通过文本引用的类的安全性premain
- 执行代理类的静态代码转换,用
替换所有调用editClass(String)
editClass(Class) 这应该不会太难,因为您只需将
,ldc packagename/Foo.class
的所有序列替换为invokestatic(Ljava/lang/class;)V
,ldc“packagename.Foo”
invokestatic(Ljava/lang/String;)V
如果方法
可以处理内部类名(使用斜杠而不是点),则可能会变得更简单。editClass(String qualifiedName)
既然您说您“最近发现了Java工具”,这可能是类文件转换中的一个很好的练习 - 使用已转换的代理类(不再引用要转换的类)执行加载时转换
editClass
方法的调用方无论如何都会使用Foo
类,因此控制加载时间的尝试注定会失败(或以非常脆弱的代码告终)。链接或验证调用类时,可以加载Foo
类。