26

我想在将源代码传递给编译器之前在编译时转换java 源代码。换句话说,我想创建一个能够转换的预处理器

"bla bla bla" 

进入任何其他代码,例如:

new MyClass("bla", 3) 

我的实际动机是进行字符串加密,如此处所述

有些人建议编写自定义注释处理器,但据我了解注释:

  • 它们可用于生成新的类文件,但不能在传递给编译器之前转换现有代码
  • 它们似乎适用于包、类或方法级别,但不适用于方法体/实现。

有人建议使用 Spoon 或 ObjectsWeb ASM 等框架,但这些框架在现有代码库上学习和部署似乎很复杂。

我很高兴为这两种方法找到一个简单的 java 代码预处理示例。

有没有人看到任何进行代码转换的聪明方法,而无需完全改变具有多个常春藤模块的现有大型代码库?注释似乎是最好的方法,但我不明白该怎么做。

4

4 回答 4

13

我认为您可以尝试在Project Lombok中使用的相同技术

作者在本次采访中大致解释了这一点:

引擎盖下发生了什么?即,注释如何导致样板文件以字节码结尾?

Reinier:注解处理器 API 只允许您创建新文件,它不允许您修改其中包含注解的文件。这就是 Lombok 所做的,因此 Lombok 不使用注释处理器 API。

相反,Lombok 仅将注解处理器 API 用作将自身注入编译过程的一种机制。所有注解处理器都在编译过程的早期初始化,Lombok 在初始化为注解处理器时会修改 javac。我们只改变一件事:AST(原始源代码,解析成树形)首先交给 Lombok,在 javac 继续之前,Lombok 会生成需要生成的任何内容。

在龙目岛是如何工作的?

也可以根据您的需要扩展 Project Lombok

于 2012-05-08T09:25:31.940 回答
2

有人已经在 python/jython 中编写了一个类似 C 的小型预处理器 ant 插件。你可以在这里找到它。请注意,我从未使用过它,但也许它可以成为满足您需求的一个很好的起点。

google 代码中还有一个java-comment-preprocessor maven 插件(类似样式),这也可能是一个有用的起点。

祝你好运。听起来是个有趣的挑战。当然,请记住,混淆只是让提取字符串变得更具挑战性,但仍然不是不可能的。如果你真的想让它变得更加困难,那么你可能想看看加密你的字符串和/或使用 AOP。

于 2012-05-07T15:09:17.957 回答
0

如果 C 预处理器就足够了,我确实设法让它在 Windows 中与 Eclipse 一起工作。它只适用于朱诺。

https://stackoverflow.com/a/10497206/1137626

于 2012-05-08T11:12:00.560 回答
0

也许重新考虑勺子?一旦你知道抽象语法树是什么,它就很直观了。您基本上可以导航、过滤和替换 AST 上代表您的代码的节点,直到您获得所需的转换。

如果我们有以下类:

public class Test {
    Object method(){
        return "bla bla bla";
    }
}

您的示例可能的 Spoon 解决方案是:

Launcher spoon = new Launcher();
spoon.addInputResource("./src/main/java/Test.java");
spoon.buildModel();
CtClass ctClass = spoon.getModel().getRootPackage().getType("Test");
CtLiteral match = ctClass.filterChildren((CtLiteral l) -> l.getType().getSimpleName().equals("String") && l.getValue().equals("bla bla bla")).first();
Factory factory = spoon.getFactory();
match.replace(factory.createCodeSnippetExpression("new MyClass(\"bla\", 3)"));
System.out.println(ctClass);

前四行构建输入程序的 Spoon 模型并检索感兴趣的类元素。

接下来要修改的文字使用过滤器检索,该过滤器返回类型为 name"String"和 value的第一个也是唯一的文字"bla bla bla"

最后匹配的文字在 AST 中被替换为所需的代码片段。使用代码构造类将代码片段从字符串自动解析为 Spoon 模型Factory

打印类模型时,会给出所需的转换:

public class Test {
    java.lang.Object method() {
        return new MyClass("bla", 3);
    }
}
于 2020-11-27T07:53:14.010 回答