java - 在编译类中不进行反射的序列化

标签 java serialization code-generation bytecode-manipulation

由于客户端 JVM 的限制,由于不支持反射,我无法使用任何流行的序列化程序。我正在寻找一种执行字节码操作的工具,通过将编写器和读取器方法注入(inject)已编译的类来实现序列化。 我需要字节码操作 java 代码来将其与我的代码绑定(bind)以构建过程。

我一直在通过生成代码并将其注入(inject)源代码,然后再编译以使用我的自定义序列化程序来执行此操作。我想避免这种方法,因为我不想让您以任何方式修改源文件。

我知道 Kryo 和其他 XML 和 JSON 序列化程序,但它们不符合我的需求。

谢谢。

最佳答案

尝试 javassist .对于您的特定项目,它可能是最直接的字节码生成库。

那是因为您将能够重用当前代码生成器的一部分,因为 javassist 能够解析一些简单形式的 Java 代码。

例如你可以这样做:

CtClass clazz = ...;
CtMethod m = CtNewMethod.make(
    "public void serialize(java.io.DataOutput out) {  out.writeInt(x); }",
     clazz);

如果你想深入了解字节码生成,你可以尝试 asm . Asm 将允许您直接编写字节码,但对于您这种类型的问题来说,这似乎有点矫枉过正。

用 javassist 实现

这是使用 javassist 执行此操作的基本框架:

Path inputDir = Paths.get("target/classes");
Path outputDir = Paths.get("target/classes2");

ClassPool classPool = new ClassPool(true);
classPool.appendClassPath(inputDir.toString());

// get all class names from a certain directory
String[] classNames = Files.walk(inputDir)
        .filter(p -> (!Files.isDirectory(p)) && p.toString().endsWith(".class"))
        .map(p -> inputDir.relativize(p).toString())
        .map(s -> s.substring(0, s.length() - 6).replace(File.separatorChar, '.'))
        .toArray(size -> new String[size]);

for (String className : classNames) {
    CtClass clazz = classPool.get(className);
    // add further filtering to select the classes you want.

    // ex: "public void serializer(java.io.DataOutput out) { out.writeInt(x); } }"
    String serializerBody = generateSerializer(clazz);
    clazz.addMethod(CtNewMethod.make(serializerBody, clazz));

    // ex: "public void deserializer(java.io.DataInput in) { x = in.readInt(); } }";
    String deserializerBody = generateDeserializer(clazz);
    clazz.addMethod(CtNewMethod.make(deserializerBody, clazz));

    // save the modified class
    clazz.setModifiers(clazz.getModifiers() & ~Modifier.ABSTRACT);
    byte[] bytes = clazz.toBytecode();
    Path outFile = outputDir.resolve(className.replace('.', '/') + ".class");
    Files.createDirectories(outFile.getParent());
    Files.write(outFile, bytes);
}

依赖性:org.javassist:javassist:3.19.0-GA

关于java - 在编译类中不进行反射的序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29821376/

相关文章:

javascript - EF -> WCF -> JSON

python - 需要对 Django REST Framework 中的序列化程序的 `Including extra context` 进行说明

java - 使用 Java 在编译时生成代码?

sql - 如何从聊天 gpt 响应中仅提取代码内容?

java - 警告 : There is no class model available for code generation in Visual Paradigm

java - Java 旅行商

javascript - 给定 LatLng 位置和方位 Angular 计算多边形边缘的位置

快速生产者的 Java "Tiered Queue"实现,慢速消费者

java - 一个类如何同时扩展和实现其他类和接口(interface)?

c# - 使用 Json.NET 序列化 XNA 矩形