JavaSsist: toBytecode() throws exception java.lang.RuntimeException: remaper.by.moofMonkey.Main class is frozen 但他没有被冻结

JavaSsist: toBytecode() throws exception java.lang.RuntimeException: remaper.by.moofMonkey.Main class is frozen but him isn't frozen

如果我在上下文中调用 toBytecode() 方法,它会抛出

java.lang.RuntimeException: remaper.by.moofMonkey.Main class is frozen at javassist.CtClassType.checkModify(CtClassType.java:515) at javassist.CtClass.getClassFile(CtClass.java:524) at com.moofMonkey.Main.writeFile(Main.java:340) at com.moofMonkey.Main.saveClasses(Main.java:324) at com.moofMonkey.Main.main(Main.java:309)

我的背景:

.....
for (CtClass cl : modClasses) {
    cl.stopPruning(true);
    writeFile(cl, "./ModifiedClasses"); //cl.writeFile("./ModifiedClasses");
    cl.stopPruning(false);
}
.....
public static void writeFile(CtClass cl, String directoryName) throws Throwable {
    System.out.println(">> " + cl.getName());

    byte[] bc = cl.toBytecode();

    String s = cl.getClassFile().getSourceFile();
    int index = new String(bc).indexOf(s);
    for(int i = 0; i < s.length(); i++)  //KILL SOURCEFILE (c) moofMonkey
        bc[index + i] = '-';

    DataOutputStream out = cl.makeFileOutput(directoryName);

    out.write(bc);

    out.flush();
    out.close();
}

但是……但是。如果我调用 writeFile() 的模拟 - cl.writeFile() - 一切正常!

我能做到:

1. Save File
2. Read bytes from him
3. Dp what I need
4. Save File

异常不是出现在您调用 toBytecode 的地方,而是出现在您调用 getClassFile 的下一个源代码行中。 documentation 说你不能在冻结的 class 上调用它。

有一个名为 getClassFile2 的方法似乎可以解决这个问题:

Returns a class file for this class (read only). Normal applications do not need calling this method. Use getClassFile().

The ClassFile object obtained by this method is read only. Changes to this object might not be reflected on a class file generated by toBytecode(), toClass(), etc.

This method is available even if isFrozen() is true. However, if the class is frozen, it might be also pruned.

第一段建议,如果有某种方法可以重组您的代码,那么它不需要为冻结的 class 获取 class 文件,那可能会更好(或至少Javassist 的创建者认为更好)。

查看 CtClass 的 javadoc 揭示

Once this method is called, further modifications are not possible any more.

如果将调用顺序更改为

String s = cl.getClassFile().getSourceFile();
byte[] bc = cl.toBytecode();

你可以打电话给toBytecode.