2023-01-19 384
我正在尝试通过使用 asm 4.0 用非 – native stubs替换所有native方法.
到目前为止,我有这个:
class ClassAdapter extends ClassVisitor {
public ClassAdapter(ClassVisitor cv) {
super(Opcodes.ASM4, cv);
}
@Override
public MethodVisitor visitMethod(int access, String base, String desc, String signature, String[] exceptions) {
return cv.visitMethod(access & ~Opcodes.ACC_NATIVE, base, desc, signature, exceptions);
}
}
由
执行
private static byte[] instrument(byte[] originalBytes, ClassLoader loader) {
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
ClassAdapter adapter = new ClassAdapter(cw);
ClassReader cr = new ClassReader(originalBytes);
cr.accept(adapter, ClassReader.SKIP_FRAMES);
return cw.toByteArray();
}
看起来很简单:我从visitMethod()中剥离了ACC_NATIVE,然后将其他所有内容保持不变.但是,当我这样做时,它会死于
Exception in thread "main"
Exception: java.lang.StackOverflowError thrown from the UncaughtExceptionHandler in thread "main"
stackoverflow发生在 instrumentation 时间上,而不是在运行时,我认为这很不寻常.但是,如果我删除& ~Opcodes.ACC_NATIVE修饰符,java.lang.Object将重写(在这种情况下不变)并完美执行.
显然我不是在做正确的事,而用非 – native方法替换native方法并不像脱离该方法上的native修饰符那样简单,但是我不知道在哪里开始. asm docs”> asm docs 不要谈论完全使用native方法.有没有与ASM合作的经验的人知道我需要做什么才能重新编写工作?
对不起,简短的,无用的消息是e.printStackTrace()给我的,但是使用e.getStackTrace()我设法获得了一些有用的东西:
java.util.concurrent.ConcurrentHashMap.hash(ConcurrentHashMap.java:332)
java.util.concurrent.ConcurrentHashMap.put(ConcurrentHashMap.java:1124)
java.util.Collections$SetFromMap.add(Collections.java:3903)
sandbox.classloader.MyClassLoader.instrument(Unknown Source)
sandbox.classloader.MyClassLoader.loadClass(Unknown Source)
java.lang.ClassLoader.defineClass1(Native Method)
java.lang.ClassLoader.defineClass(ClassLoader.java:791)
java.lang.ClassLoader.defineClass(ClassLoader.java:634)
sandbox.classloader.MyClassLoader.findClass(Unknown Source)
sandbox.classloader.MyClassLoader.loadClass(Unknown Source)
sandbox.Tester.main(Unknown Source)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:601)
com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
因此,在我看来,错误实际上是在执行时间发生的(例如,我认为这是在仪器时间时被误认为),这是调用hashCode()的结果.碰巧的是,hashCode()我(可能错误地)剥离了它的native修饰符的本机方法之一.很明显,它是呼叫 native分割的方法,引起了问题.
看起来真正的奇怪的是,堆栈跟踪只有16帧深;考虑到它是StackOverflowError,我会期望更多.
用存根替换本机代码并不那么简单,但是离该
不远
如果您查看 classVisitor#vistmethod(int access,int access,int access,string name,字符串desc,string desc,string string string string string string string string string string string string string签名,字符串[]异常)
您会看到它返回MethodVisitor
methodvisitor 哪个您现在必须使用.如果要制作抽象的存根,则至少应将呼叫添加到methodVisitor.visitEnd()
如果要制作空存根
在此详细说明这是一个仪器代理的完全工作示例,该仪器使用ASM用返回固定值的存根代替本机方法java.net.NetworkInterface#getHardwareAddress().
public class MacModifyAgent {
private static final String TARGET = "java/net/NetworkInterface";
public static void premain(String agentArgs, Instrumentation inst) {
inst.addTransformer(new ClassFileTransformer() {
@Override
public byte[] transform(ClassLoader l, String name, Class<?> c, ProtectionDomain d, byte[] b)
throws IllegalClassFormatException {
if (TARGET.equals(name)) {
return instrument(b);
}
return b;
}
});
}
private static byte[] instrument(byte[] originalBytes) {
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
ClassAdapter adapter = new ClassAdapter(cw);
ClassReader cr = new ClassReader(originalBytes);
cr.accept(adapter, ClassReader.SKIP_FRAMES);
return cw.toByteArray();
}
public static class ClassAdapter extends ClassVisitor implements Opcodes {
public ClassAdapter(ClassVisitor cv) {
super(ASM4, cv);
}
@Override
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature,
String[] exceptions) {
if ("getHardwareAddress".equals(name)) {
MethodVisitor mv = super.visitMethod(access & ~ACC_NATIVE, name, descriptor, signature, exceptions);
MethodVisitor special = new StubReturnValue(mv, new byte[] { 1, 2, 3, 4, 5, 6 });
return special;
} else {
return super.visitMethod(access, name, descriptor, signature, exceptions);
}
}
}
public static class StubReturnValue extends MethodVisitor implements Opcodes {
private final MethodVisitor target;
private byte[] mac;
public StubReturnValue(MethodVisitor target, byte [] mac) {
super(ASM4, null);
this.target = target;
}
@Override
public void visitCode() {
target.visitCode();
target.visitVarInsn(BIPUSH, 6);
target.visitIntInsn(NEWARRAY, T_BYTE);
for (int i = 0; i < 6; i++) {
target.visitInsn(DUP);
target.visitIntInsn(BIPUSH, i);
target.visitIntInsn(BIPUSH, mac[i]);
target.visitInsn(BASTORE);
}
target.visitInsn(ARETURN);
target.visitEnd();
}
}
}
以上所述是小编给大家介绍的使用ASM重写Java本机方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对77isp云服务器技术网的支持!
原文链接:https://77isp.com/post/25767.html
=========================================
https://77isp.com/ 为 “云服务器技术网” 唯一官方服务平台,请勿相信其他任何渠道。
数据库技术 2022-03-28
网站技术 2022-11-26
网站技术 2023-01-07
网站技术 2022-11-17
Windows相关 2022-02-23
网站技术 2023-01-14
Windows相关 2022-02-16
Windows相关 2022-02-16
Linux相关 2022-02-27
数据库技术 2022-02-20
抠敌 2023年10月23日
嚼餐 2023年10月23日
男忌 2023年10月22日
瓮仆 2023年10月22日
簿偌 2023年10月22日
扫码二维码
获取最新动态