Как использовать аннотации java для изменения исходного кода перед окончательной компиляцией?
Я прочитал на странице инструмента apt, что можно создать AnnotationProcessors для генерировать новые производные файлы (исходные файлы, файлы классов, дескрипторы развертывания и т.д.).. Я ищу пример для этого.
Мне нужно кодировать все аннотированные строки во время компиляции, поэтому чтение файла класса не позволяет читать статические строки:
Базовый код:
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)
структуры TrueLicense процессор может сгенерировать код для замены аннотированной строки. В самом деле, этот метод генерирует строку "новый ObfuscatedString ([numeric_code]). ToString()".
Во время выполнения метод toString() ObfuscatedString может возвращать строку, закодированную в числовом коде.
Любая идея о том, как написать метод process() AnnotationProcessor для редактирования аннотированного кода?
Спасибо заранее,
Ответы
Ответ 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);
Ответ 2
Я уверен, что spoon может быть тем, что вы ищете. Но почему вы хотите обфускать статические строки?
Ответ 3
Zelix KlassMaster предлагает эту возможность. Если память работает, она была бесплатной для компаний в возрасте до 3 разработчиков, но я только что проверил их страницу покупки, и кажется, что теперь они взимают плату за небольшие разработчики для небольших компаний. Я не использовал его в течение нескольких лет (по крайней мере 5 или 7), но он сделал фантастическую работу, запутывая строки и код в целом.
Ответ 4
Когда я собираюсь сгенерировать версию для его распространения, у меня есть класс, который переопределяет все константы с вызовом Ofuscated String:
Это процесс:
- Я запустил свой ANT, который копирует весь код в другое место.
- ANT вызов OfuscateJavaConstant.
- Компилируем код.
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();
}
}
}
Надеюсь, это поможет:)