gpt4 book ai didi

java - asm 类文件太大

转载 作者:行者123 更新时间:2023-12-02 02:23:32 25 4
gpt4 key购买 nike

向类添加代码时,遇到运行时异常“类文件太大!”由ClassWriter.toByteArray()触发。

有解决方法可以解决此问题吗?例如,如果一个方法太大,我们可以将其拆分来解决问题,但是类呢?

PS:使用asm 5.0.1

ClassReader 和 ClassWriter 的初始化

    ClassReader classReader = new ClassReader(in);
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS);

MyClassVisitor myClassVisitor = new MyClassVisitor(Opcodes.ASM5, classWriter);
classReader.accept(myClassVisitor, ClassReader.SKIP_DEBUG);

对于仪器,我只是通过将指令编号压入堆栈并在每条指令后添加一个调用来记录正在执行的指令(因此每条指令+2)

@Override
public void visitVarInsn(int opcode, int var) {
logInstruction();
super.visitVarInsn(opcode, var);
count++; // instruction number
}
private void logInstruction(){
super.visitLdcInsn(count);
super.visitMethodInsn(Opcodes.INVOKESTATIC, "Logger", "logInstruction",
Type.getMethodDescriptor(Type.VOID_TYPE, Type.INT_TYPE), false);
}

最佳答案

当类文件大小太大时,不会抛出RuntimeException(“类文件太大!”)(如果你的类文件超过2GiB,那就真的很奇怪了),而是抛出当常量池中的项数超过65534时。

遇到此类文件限制仍然是相当不寻常的。因此我建议重新检查您是否使用了优化的仪器。当您将 ClassReader 传递给 the ClassWriter’s constructor 时,它将复制旧类的整个常量池,如果您只进行微小的更改,这很适合。

但是,如果您正在执行重大更改,例如重命名成员或类型,您可能会在常量池中留下大量未使用的旧条目,同时添加大量新条目。不将读取器传递给写入器的构造函数会牺牲性能,但会创建一个仅包含所需条目的新常量池。如果仅此还不够,您可以通过 SKIP_DEBUGClassReader 的构造函数中删除调试信息,进一步减少常量池项的数量。

如果仍然没有帮助,您必须重新设计您要注入(inject)的内容。对于此类代码,适用与普通手写代码相同的规则。将代码拆分为合理大小的方法,重用公共(public)代码,将方法组织在类中。毕竟,如果您只是注入(inject)现有方法的调用,那么即使代码注入(inject)本身也会变得更简单、更高效。

<小时/>

问题在于您的 super.visitLdcInsn(count); 指令。这将为每个不同的整数值创建一个新的常量池条目。由于指令号可以是 065535 之间的任何整数,因此这很容易超出可能的常量池条目的数量。

对于该范围内的值,您不需要使用常量池条目。对于小整数值有专用的字节码指令。但一般来说,创建一个实用方法为每个 int 值创建最佳指令是值得的:

public final void push(final int value) {
if(value >= -1 && value <= 5) {
super.visitInsn(Opcodes.ICONST_0 + value);
} else if(value == (byte)value) {
super.visitIntInsn(Opcodes.BIPUSH, value);
} else if(value == (short)value) {
super.visitIntInsn(Opcodes.SIPUSH, value);
} else {
super.visitLdcInsn(value);
}
}

然后,一般使用push(intNumber)而不是visitLdcInsn(intNumber)

关于java - asm 类文件太大,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48120065/

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