如何在最终编译之前使用java注释修改源代码?

时间:2011-07-01 12:09:17

标签: java annotations apt

我从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()方法来编辑带注释的代码?

提前致谢,

4 个答案:

答案 0 :(得分:2)

你可以

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);

答案 1 :(得分:2)

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

答案 2 :(得分:1)

Zelix KlassMaster提供此功能。如果内存服务,以前对3岁以下的公司免费,但我刚刚检查了他们的购买页面,现在看来他们现在收取小公司的小开发费。我好几年没用过它了(至少5或7),但是它在字符串和代码方面做了很棒的工作。

答案 3 :(得分:1)

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

这是一个过程:

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

     <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();
             }
        }
    
    }
    

    希望有所帮助:)