Bytecode dönüştürme
- Java kursu
- Uzman
- Ders 40/46
- 6 dk
ASM ile bytecode dönüştürme yazarsın.
dönüştürücü visitor
Bir visitor, başka bir visitor'ı sarıp olayları değiştirebilir. Bu sarmalayıcı (decorator) deseni, ASM ajanlarının temelidir. RenameVisitor, içteki delegate visitor'a olayları iletirken metot adlarını değiştirebilir.
Örneğin visitMethod'ta n.replace("main", "start") yapıp delegate'e iletirsen, çıktıda main yerine start görünür. Dönüşüm şeffaftır: delegate yine aynıvisitor mantığını çalıştırır.
delegate sarmalama
RenameVisitor bir ClassVisitor delegate'ini kurucuda alır ve saklar. Her olayda önce dönüşümü uygular, sonra delegate'e iletir. visitClass'ta adı değiştirmeden geçirirken, visitMethod'ta yeniden adlandırma yapabilir.
Bu desen, ASM'de bayt kodu dönüştüren ajanlarda kullanılır: bir visitor zinciri kurulur, her halka bir işlem ekler. Son halka genelde ClassWriter'dır.
Uygulama RenameVisitor sınıfını yaz
Üstteki yapıya class RenameVisitor implements ClassVisitor ekle; ClassVisitor delegate alanı ve RenameVisitor(ClassVisitor delegate) yapıcısı olsun. visitClass(String n) metodu delegate.visitClass(n);, visitMethod(String n) metodu delegate.visitMethod(n.replace("main", "start")); çağırsın. main içinde ClassWriter writer = new ClassWriter(); oluştur, reader.accept(new RenameVisitor(writer)); çağır ve System.out.println(writer.toString()); ile yazdır.
Başlangıç kodu
interface ClassVisitor {
void visitClass(String name);
void visitMethod(String name);
}
class ClassReader {
String name;
String[] methods;
ClassReader(String name, String[] methods) {
this.name = name;
this.methods = methods;
}
void accept(ClassVisitor v) {
v.visitClass(name);
for (String m : methods) v.visitMethod(m);
}
}
class ClassWriter implements ClassVisitor {
StringBuilder sb = new StringBuilder();
public void visitClass(String n) { sb.append("Class: ").append(n).append("\n"); }
public void visitMethod(String n) { sb.append("Method: ").append(n).append("\n"); }
public String toString() { return sb.toString().trim(); }
}
public class Main {
public static void main(String[] args) {
ClassReader reader = new ClassReader("Main", new String[]{"main"});
ClassWriter writer = new ClassWriter();
reader.accept(writer);
System.out.println(writer.toString());
}
}Örnek çözüm
interface ClassVisitor {
void visitClass(String name);
void visitMethod(String name);
}
class ClassReader {
String name;
String[] methods;
ClassReader(String name, String[] methods) {
this.name = name;
this.methods = methods;
}
void accept(ClassVisitor v) {
v.visitClass(name);
for (String m : methods) v.visitMethod(m);
}
}
class ClassWriter implements ClassVisitor {
StringBuilder sb = new StringBuilder();
public void visitClass(String n) { sb.append("Class: ").append(n).append("\n"); }
public void visitMethod(String n) { sb.append("Method: ").append(n).append("\n"); }
public String toString() { return sb.toString().trim(); }
}
class RenameVisitor implements ClassVisitor {
ClassVisitor delegate;
RenameVisitor(ClassVisitor delegate) {
this.delegate = delegate;
}
public void visitClass(String n) { delegate.visitClass(n); }
public void visitMethod(String n) { delegate.visitMethod(n.replace("main", "start")); }
}
public class Main {
public static void main(String[] args) {
ClassReader reader = new ClassReader("Main", new String[]{"main"});
ClassWriter writer = new ClassWriter();
reader.accept(new RenameVisitor(writer));
System.out.println(writer.toString());
}
}Beklenen çıktı
Class: Main Method: start
Soru ve cevaplar
Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.
1 yeniden adlandırma çağrısını tamamla
return name.____("main", "start");
return name.replace("main", "start");
Açıklama: name.replace("main", "start") metodu yeniden adlandırır.
2 Dönüştürücü visitor ne yapar?
- Olayları değiştirerek iletir Doğru cevap
- Bayt kodu derler
- Thread başlatır
- Sınıfı siler
Açıklama: Dönüştürücü visitor olayları değiştirip delegate'e iletir.
3 dönüşüm öğelerini eşleştir
| Kavram | Anlamı |
|---|---|
delegate |
Sarmalanan visitor |
replace |
Yeniden adlandırma |
visitMethod |
Metot olayı |
RenameVisitor |
Dönüştürücü sınıf |