ASM については以前に詳しく紹介しました。必要な方はここをクリックしてください: Java バイトコード フレームワーク ASM の詳細な研究
JVM タイプ署名比較表
たとえば、Java メソッドは
long f (int n, String s, int[] arr);です。
の型署名は
f (ILjava/lang/String;[I)J
別の例として、Java メソッドが
private void hi(double a, List<String> b);
の場合、対応する型署名は
hi (DLjava/util/List;)V
次に、ASM を使用して、上記の 2 つが一致しているかどうかを確認できます。型署名は正しいです:
public class Test { public static void main(String[] args) throws Exception { ClassPrinter printer = new ClassPrinter(); //读取静态内部类Bazhang ClassReader cr = new ClassReader("Test$Bazhang"); cr.accept(printer, 0); } //静态内部类 static class Bazhang { public Bazhang(int a) { } private long f (int n, String s, int[] arr){ return 0; } private void hi(double a, List<String> b){ } } static class ClassPrinter extends ClassVisitor { public ClassPrinter() { super(Opcodes.ASM5); } @Override public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { super.visit(version, access, name, signature, superName, interfaces); //打印出父类name和本类name System.out.println(superName + " " + name); } @Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { //打印出方法名和类型签名 System.out.println(name + " " + desc); return super.visitMethod(access, name, desc, signature, exceptions); } } }
最後に出力された内容:
java/lang/Object Test$Bazhang <init> ()V f (ILjava/lang/String;[I)J hi (DLjava/util/List;)V
は以前の正しさを検証し、デフォルトのコンストラクターも出力されていることがわかります。
次に、Bazhang クラスに新しいメソッドを追加しましょう。
public void newFunc(String str){ }
この時点では、特に ClassReader についてのバイトコードを結合するために使用される ClassWriter を使用する必要があります。 ClassVisitor と ClassWriter の記事では、この記事を参照できます: ASM ソース コード学習のための ClassReader、ClassVisitor、および ClassWriter の詳細な説明
public static void main(String[] args) throws Exception { ClassReader cr = new ClassReader(Bazhang.class.getName()); ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS); cr.accept(cw, Opcodes.ASM5); MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "newFunc", "(Ljava/lang/String;)V", null, null); mv.visitInsn(Opcodes.RETURN); mv.visitEnd(); // 获取生成的class文件对应的二进制流 byte[] code = cw.toByteArray(); //将二进制流写到out/下 FileOutputStream fos = new FileOutputStream("out/Bazhang222.class"); fos.write(code); fos.close(); }
これにより、 out/ フォルダーに Bazhang222.class が生成されます:
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // import java.util.List; class Test$Bazhang { Test$Bazhang() { } private long f(int n, String s, int[] arr) { return 0L; } private void hi(double a, List<String> b) { } public void newFunc(String var1) { } }
以前にコンパイルされた JVM 命令セットを結合し、ASM を使用してバイトコードを直接操作しても問題ありません。最後に ASM ソース コードのダウンロード アドレスが添付されます: http://forge.ow2.org/projects/asm/
。まとめ
以上です。この記事の内容が皆さんの学習や仕事に少しでもお役に立てれば幸いです。ご不明な点がございましたら、メッセージを残してください。
Java バイトコード フレームワーク ASM がバイトコードを操作する方法に関するその他の関連記事については、PHP 中国語 Web サイトに注目してください。