3.深刻jvm内核-原理、诊断与优化-10. jvm字节码执行

1、字节码java

javap
简单的字节码执行过程
经常使用的字节码
使用ASM生成Java字节码
JIT及其相关参数
  1. javap(class文件反汇编工具)web

    public class Calc {
    		public int calc() {
    			int a = 500;
    			int b = 200;
    			int c = 50;
    			return (a + b) / c;
    		}
    	}
    javap –verbose Calc

  2. 简单的字节码执行过程app

  3. 经常使用的字节码jvm

  4. 经常使用的字节码工具

  5. 使用ASM生成Java字节码性能

    例子:this

    <dependency>
            <groupId>org.ow2.asm</groupId>
            <artifactId>asm</artifactId>
            <version>5.0.3</version>
        </dependency>

    GrandParent.java.net

    public class GrandParent {
    		public void test() {
    				System.out.println("test of GrandParent");
    		}
    	}

    Parent.java3d

    public class Parent extends GrandParent{
    		public void test() {
    			System.out.println("test of Parent");
    		}
    	}

    Son.javacode

    public class Son extends Parent{
    		public void test() {
    			System.out.println("test of Son");
    		}
    	}

    ASMByteCodeManipulation.java

    /**
    	 * description:
    	 *
    	 * [@author](https://my.oschina.net/arthor): dawn.he QQ:       905845006
    	 * [@email](https://my.oschina.net/u/159820): dawn.he@cloudwise.com
    	 * [@email](https://my.oschina.net/u/159820): 905845006@qq.com
    	 * @date: 2019/9/30    9:21 PM
    	 */
    
    	import java.io.FileOutputStream;
    
    	import org.objectweb.asm.ClassWriter;
    	import org.objectweb.asm.MethodVisitor;
    	import org.objectweb.asm.Opcodes;
    
    	public class ASMByteCodeManipulation extends ClassLoader implements Opcodes {
    
    		public static void main(String args[]) throws Exception {
    
    			test1();
    	//        test2();
    		}
    
    		//print hello word
    		public static void test1() throws Exception{
    			ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS|ClassWriter.COMPUTE_FRAMES);
    			cw.visit(V1_7, ACC_PUBLIC, "Example", null, "java/lang/Object", null);
    			MethodVisitor mw = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null,  null);
    			mw.visitVarInsn(ALOAD, 0);  //this 入栈
    			//使用invokespecial这种方式也有局限,只能从子类调用。不然报错:
    			mw.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
    			mw.visitInsn(RETURN);
    			mw.visitMaxs(0, 0);
    			mw.visitEnd();
    			mw = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main",  "([Ljava/lang/String;)V", null, null);
    			mw.visitFieldInsn(GETSTATIC, "java/lang/System", "out",  "Ljava/io/PrintStream;");
    			mw.visitLdcInsn("Hello world!");
    			mw.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println",  "(Ljava/lang/String;)V");
    			mw.visitInsn(RETURN);
    			mw.visitMaxs(0,0);
    			mw.visitEnd();
    			byte[] code = cw.toByteArray();
    			ASMByteCodeManipulation loader = new ASMByteCodeManipulation();
    			Class exampleClass = loader
    					.defineClass("Example", code, 0, code.length);
    			exampleClass.getMethods()[0].invoke(null, new Object[] { null });
    
    		}
    		//print hello word
    		public static void test2() throws Exception{
    					ClassWriter cw = new ClassWriter(0);
    			cw.visit(V1_1, ACC_PUBLIC, "Example", null, "Son", null);
    
    			// creates a MethodWriter for the (implicit) constructor
    			MethodVisitor mw = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
    			mw.visitVarInsn(ALOAD, 0);
    			mw.visitMethodInsn(INVOKESPECIAL, "Son", "<init>", "()V");
    			mw.visitInsn(RETURN);
    			mw.visitMaxs(1, 1);
    			mw.visitEnd();
    
    			// creates a MethodWriter for the 'test' method
    			mw = cw.visitMethod(ACC_PUBLIC, "test", "()V", null, null);
    			mw.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
    			mw.visitLdcInsn("test of AI3");
    			mw.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println",
    					"(Ljava/lang/String;)V");
    			//Call test() of GrandParent
    			mw.visitVarInsn(ALOAD, 0);
    			mw.visitMethodInsn(INVOKESPECIAL, "GrandParent", "test", "()V");
    			//Call test() of GrandParent
    			mw.visitVarInsn(ALOAD, 0);
    			mw.visitMethodInsn(INVOKESPECIAL, "Parent", "test", "()V");
    			//Call test() of GrandParent
    			mw.visitVarInsn(ALOAD, 0);
    			mw.visitMethodInsn(INVOKESPECIAL, "Son", "test", "()V");
    			mw.visitInsn(RETURN);
    			mw.visitMaxs(2, 1);
    			mw.visitEnd();
    
    			byte[] code = cw.toByteArray();
    			FileOutputStream fos = new FileOutputStream("Example.class");
    			fos.write(code);
    			fos.close();
    
    			ASMByteCodeManipulation loader = new ASMByteCodeManipulation();
    			Class<?> exampleClass = loader.defineClass("Example", code, 0,
    					code.length);
    			Object obj = exampleClass.newInstance();
    			exampleClass.getMethod("test", null).invoke(obj, null);
    
    		}
    
    	}

    test2方法生成的class文件

    public class Example extends Son {
    		public Example() {
    		}
    
    		public void test() {
    			System.out.println("test of AI3");
    			super.test();
    			super.test();
    			super.test();
    		}
    	}

    例子2:

    Account.java

    public class Account {
    		public void operation() {
    			System.out.println("operation....");
    		}
    	}

    要嵌入的内容

    SecurityChecker.java

    public class SecurityChecker { 
    	 public static boolean checkSecurity() { 
    	 System.out.println("SecurityChecker.checkSecurity ...");
    	 return true;
    	 } 
    	}

    AddSecurityCheckClassAdapter.java

    import org.objectweb.asm.ClassVisitor;
    	import org.objectweb.asm.MethodVisitor;
    	import org.objectweb.asm.Opcodes;
    
    	/**
    	 * description:
    	 *
    	 * @author: dawn.he QQ:       905845006
    	 * @email: dawn.he@cloudwise.com
    	 * @email: 905845006@qq.com
    	 * @date: 2019/9/30    10:39 PM
    	 */
    	public class AddSecurityCheckClassAdapter extends ClassVisitor {
    		public AddSecurityCheckClassAdapter( ClassVisitor cv) {
    			super(Opcodes.ASM5, cv);
    		}
    		// 重写 visitMethod,访问到 "operation" 方法时,
    		// 给出自定义 MethodVisitor,实际改写方法内容
    		public MethodVisitor visitMethod(final int access, final String name,
    										 final String desc, final String signature, final String[] exceptions) {
    			MethodVisitor mv = cv.visitMethod(access, name, desc, signature,exceptions);
    			MethodVisitor wrappedMv = mv;
    			if (mv != null) {
    				// 对于 "operation" 方法
    				if (name.equals("operation")) {
    					// 使用自定义 MethodVisitor,实际改写方法内容
    					wrappedMv = new AddSecurityCheckMethodAdapter(mv);
    				}
    			}
    			return wrappedMv;
    		}
    	}

    AddSecurityCheckMethodAdapter.java

    import org.objectweb.asm.MethodVisitor;
    	import org.objectweb.asm.Opcodes;
    
    	/**
    	 * description:
    	 *
    	 * @author: dawn.he QQ:       905845006
    	 * @email: dawn.he@cloudwise.com
    	 * @email: 905845006@qq.com
    	 * @date: 2019/9/30    10:40 PM
    	 */
    	public class AddSecurityCheckMethodAdapter extends MethodVisitor {
    		public AddSecurityCheckMethodAdapter(MethodVisitor mv) {
    			super(Opcodes.ASM5,mv);
    		}
    		public void visitCode() {
    	//        visitMethodInsn(Opcodes.INVOKESTATIC, "geym/jvm/ch10/asm/SecurityChecker",
    			visitMethodInsn(Opcodes.INVOKESTATIC, "SecurityChecker",
    
    					"checkSecurity", "()Z");
    			super.visitCode();
    		}
    	}

    Generator.java

    import org.objectweb.asm.ClassReader;
    	import org.objectweb.asm.ClassWriter;
    	import org.objectweb.asm.Opcodes;
    
    	import java.io.File;
    	import java.io.FileOutputStream;
    
    	/**
    	 * description:
    	 *
    	 * @author: dawn.he QQ:       905845006
    	 * @email: dawn.he@cloudwise.com
    	 * @email: 905845006@qq.com
    	 * @date: 2019/9/30    10:40 PM
    	 */
    	public class Generator extends ClassLoader  {
    		public static void main(String args[]) throws Exception {
    	//        ClassReader cr = new ClassReader("geym.jvm.ch10.asm.Account");
    			ClassReader cr = new ClassReader("Account");
    
    			ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS|ClassWriter.COMPUTE_FRAMES);
    			AddSecurityCheckClassAdapter classAdapter = new AddSecurityCheckClassAdapter(cw);
    			cr.accept(classAdapter, ClassReader.SKIP_DEBUG);
    			byte[] data = cw.toByteArray();
    
    			//class文件写到哪里
    	//        File file = new File("bin/geym/jvm/ch10/asm/Account.class");
    			File file = new File("Account.class");
    			FileOutputStream fout = new FileOutputStream(file);
    			fout.write(data);
    			fout.close();
    
    
    			Generator loader = new Generator();
    			Class<?> exampleClass = loader.defineClass("Account", data, 0,
    					data.length);
    			Object obj = exampleClass.newInstance();
    			exampleClass.getMethod("operation", null).invoke(obj, null);
    
    		}
    	}

    执行完main方法 输出:

    SecurityChecker.checkSecurity ... operation....

    生成的class

    Account.class

    //
    	// Source code recreated from a .class file by IntelliJ IDEA
    	// (powered by Fernflower decompiler)
    	//
    
    	public class Account {
    		public Account() {
    		}
    
    		public void operation() {
    			SecurityChecker.checkSecurity();
    			System.out.println("operation....");
    		}
    	}
  6. JIT及其相关参数

    字节码执行性能较差,因此能够对于热点代码编译成机器码再执行,在运行时的编译,
     叫作JIT Just-In-Time
     JIT的基本思路是,将热点代码,就是执行比较频繁的代码,编译成机器码。

相关文章
相关标签/搜索