【问题标题】:How to use java annotations to modify source code before final compilation?最终编译前如何使用java注解修改源代码?
【发布时间】:2011-07-01 12:09:16
【问题描述】:

我从 apt 工具页面中了解到,可以将 AnnotationProcessors 创建到 generate new derived files (source files, class files, deployment descriptors, etc.)。我正在寻找这样做的例子。

我的需要是在编译时对所有带注释的字符串进行编码,这样读取类文件就不允许读取静态字符串:

基本代码:

String message = (@Obfuscated "a string that should not be readable in class file");

应该重做为:

String message = new ObfuscatedString(new long[] {0x86DD4DBB5166C13DL, 0x4C79B1CDC313AE09L, 0x1A353051DAF6463BL}).toString();

基于静态ObfuscatedString.obfuscate(String) method of the TrueLicense framework,处理器可以生成代码来替换带注释的字符串。实际上,此方法会生成字符串“new ObfuscatedString([numeric_code]).toString()”。 在运行时,ObfuscatedString 的 toString() 方法能够返回以数字代码编码的字符串。

知道如何编写 AnnotationProcessor 的 process() 方法来编辑带注释的代码吗?

提前致谢,

【问题讨论】:

  • 正是混淆器在你编译了你的源代码之后所做的。为工作使用正确的工具。
  • Proguard 不支持字符串混淆。您知道其他一些处理此功能的免费混淆器吗?

标签: java annotations apt


【解决方案1】:

你可以有

String message = Obfuscated.decode("a string that should not be readable in class file");

正常编译,但是在编译后你有一个检查字节码的工具,例如使用 ObjectWeb 的 ASM,更改字符串文字,使其看起来像

String message = Obfuscated.decode("\u86DD\u4DBB\u5166\uC13D\u4C79\uB1CD\uC313\uAE09\u1A35\u3051\uDAF6\u463B");

为了更容易识别需要更改的字符串,您可以为它们添加一个前缀,并且您可以确保该前缀确实在代码被混淆后出现。

String s = "Obfuscate: a string that should not be readable in class file";
// later
String message = Obfuscated.decode(s);

【讨论】:

  • ASM 似乎是一个非常有趣的工具,我很高兴你谈到了!我找到了一个介绍该工具的好文档 (download.forge.objectweb.org/asm/asm-guide.pdf)。但是,由于代码编辑相当简单,我想知道是否可以使用注释来避免 ASM 学习曲线......并学习注释!
【解决方案2】:

我敢打赌spoon 可能就是您要找的东西。但是为什么要混淆静态字符串呢?

【讨论】:

  • 我对编译代码中的字符串进行了混淆处理,以使我们很难找到处理我们软件许可部分的类。没有这个,很容易对代码进行逆向工程并找到要删除的“if”来解锁软件。 Spoon 对于这样的任务似乎是一个非常好的工具,它的 eclipse 集成使它与 ObjectWeb 的 ASM 一样吸引人。您对使用第一个或另一个的利弊有一些想法吗?
  • 最终似乎很难找到示例代码或对原始 java 注释有经验的人来执行我的任务。我想我会使用其中一种建议的工具。
【解决方案3】:

Zelix KlassMaster 提供此功能。内存的话,以前3人以下的公司是免费的,但是我刚查了他们的购买页面,现在好像对小公司收取小开发者费用。我已经好几年没用过了(至少 5 或 7 年),但它在混淆字符串和一般代码方面做得非常出色。

【讨论】:

    【解决方案4】:

    当我要生成版本以分发它时,我有一个类可以使用 Ofuscated String 调用覆盖所有常量:

    这是过程:

    1. 我运行我的 ANT,它将所有代码复制到其他地方。
    2. 对 OfuscateJavaConstant 的 ANT 调用。
    3. 我编译代码。

    蚂蚁:

     <java classname="de.schlichtherle.util.ObfuscatedString">
         <arg value="${of.constant}" />
         <classpath>
             <pathelement location="${exit.path}/${buildDir}" />
             <path refid="myclasspath" />
         </classpath>
      </java>
    

    Java Ofuscate 代码(ObfuscatedString):

    public static void main(String[] args) {
        if ( args!=null ){
            String[] ficheros = args[0].split(";");
    
            if ( args!=ficheros )
                for (String ruta:ficheros)
                    ofuscateConstantClass( ruta );
        }
    }
    
    private static void ofuscateConstantClass( String fileName ){
    
        File archivo = null;
        FileReader fr = null;
        BufferedReader br = null;
        List<String> sb  = new ArrayList<String>();
        FileWriter fichero = null;
        PrintWriter pw = null;
    
        try{
            archivo = new File( fileName );
            fr = new FileReader (archivo);
            br = new BufferedReader(fr);
            String linea;
            while( (linea=br.readLine())!=null ){
    
                String noWhite = linea.trim().replaceAll(" +", " ");
    
                if ( noWhite.toLowerCase().startsWith("public static final string") && noWhite.endsWith("\";") ){
    
                    String firstPart = noWhite.substring(0, noWhite.indexOf("\"") );
                    String constant = noWhite.substring(noWhite.indexOf("\"")+1, noWhite.lastIndexOf("\"") );
                    String ofuscatedConstant = obfuscate( constant );
                    String secondPart = noWhite.substring(noWhite.lastIndexOf("\"")+1 );
                    sb.add( firstPart + ofuscatedConstant + secondPart );
                    System.out.println( constant + "-->" + ofuscatedConstant );
                } else
                    sb.add( linea );
            }
    
            fichero = new FileWriter( fileName );
            pw = new PrintWriter(fichero);
            for (String s:sb)
                pw.println( s );
    
        } catch ( Exception e){
    
        } finally {
             try{
                 if( null != fr )
                     fr.close();
                 if( null != pw )
                     pw.close();
                 if( null != fichero )
                     fichero.close();
             }catch (Exception e2){
                e2.printStackTrace();
             }
        }
    
    }
    

    希望对你有帮助:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-06
      相关资源
      最近更新 更多