编译时的Java代码转换

时间:2012-05-07 13:58:50

标签: java compilation code-translation

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

"bla bla bla" 

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

new MyClass("bla", 3) 

我的实际动机是进行字符串加密,如explained here

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

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

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

我很想找到一个简单的java代码预处理示例。

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

4 个答案:

答案 0 :(得分:9)

我认为您可以尝试Project Lombok

中使用的相同技巧

作者在this interview中大致解释了:

  

引擎盖下发生了什么?也就是说,样板中的注释结果如何以字节码结束?

     

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

     

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

How does lombok work?

也可以将Project Lombok扩展到您的需求

答案 1 :(得分:2)

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

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

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

答案 2 :(得分:0)

如果C预处理器就足够了,我确实设法让它在Windows中使用Eclipse。它只适用于Juno。

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

答案 3 :(得分:0)

也许重新考虑勺子?一旦您知道abstract syntax tree是什么,它就很直观。您基本上可以导航,过滤和替换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模型并检索感兴趣的类元素。

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

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

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

public class Test {
    java.lang.Object method() {
        return new MyClass("bla", 3);
    }
}