java类执行机制

java类得执行机制分为字节码解释执行和编译为机器码执行,后者又分为client compiler 和server compiler

1、字节码解释执行

JVM是一种中间代码的方式 ,在执行时候,JVM有自己的一套指令,JVM采用invokestatic、invokevirtual、invokeinterface、invokespecial来查找执行不同的方法。

invokestatic会调用static方法,invokevirtual会调用对象实例的方法,invokeinterface会调用接口的方法,invokespecial会调用私有的方法和编译之后<init>方法,此方法为对象实例化的初始化方法,如下面的代码:

public class Demo{
    public void execute{
       A.execute();//调用invokestatic
       A a =new A();//调用invokespecial
       a.am();//调用invokevirtual
       IB b = new B();//调用invokespecial
       b.bm();//调用invokeinterface
    }
}
public class A{
     public static String execute(){
        return "A";
    }
    public am(){
       return "am";
   }
}
public interface IB{
    public String mb();
}
public class B implements IB{
    public String mb{
       return "mb";
    }
}

以上是四种指令对应方法的情况。

2、编译执行

 1)client compiler(C1)

client compiler又称为C1,只做少量性能开销比较高的优化,占内存比较小,适合桌面应用程序,其中采用的优化方式主要有方法内联、冗余消除、去虚拟化等。

 ①方法内联

 通常一个业务逻辑方法,要调用多个方法来完成,所谓的方法内联就是把方法体内的代码直接植入到当前的方法体内,如下面代码:

public void m1(){
		//.....
		m2();
		//...
	}
private void m2(){
		//do.....
	}
当编译的时候 ,m2()字节数小到规定范围内时候,就会将m2()的方法体直接植入到m1()内,如下:

public void m1(){
		//.....
		//do.....
		//...
}

可以在debug版本的JDK启动参数加上:-XX:+PrintLnLining来查看先关的内联信息。

②去虚拟化

主要是对类层次进行分析,当一个借口只有一个实现类的时候,那么在调用方法的时候,会将方法植入到方法体内,如:

piblic interface IParent(){
	public void m();
}

public Child implements Iparent{
	public void m(){
		//do.....
	}
}

public class Demo{
	public void ip(Iparent child){
		child.m();
	}
}
由于只有Child实现IParent,最后编译的代码为:

public void ip(Iparent child){
		//do....
}

③冗余消除

主要精简代码和消除无用的代码

如:

boolean status = false;
public void m(){
	if(status){
		//do....
	}
      //do..something.......
}
编译之后为:

public void m(){
	//do...something....
}

2)server compiler(C2)

C2占用的内存比较多,但是用很多的优化技巧,它是基于逃逸分析进行优化的,所谓逃逸分析,就是一个方法内的一个变量 ,如果没有被外部引用过,那么就认为该变是逃逸的,否则是没有逃逸,基于逃逸分析的C2会做标量替换、栈上分配、同步消除等。

①标量替换

就是变量替换聚合量,如:

B b = new B("Tom mao");
System.out.println(b.name);

如果b在之后没有被用到过,那么标量替换后的代码为:

String name = "Tom mao";
System.out.println(name);
②栈上分配

就是把局部变量直接分配在栈上,当方法结束后 ,标量占用的内存也会随之而释放。

③同步消除

就是如果发现同步的对象 没有逃逸,那么就没有同步的必要,就会去掉同步的代码。

默认情况下 SUN JDK会根据机器的配置来选择相应的编辑为机器码方式,当机器配置cpu超过2核且内存超过2G会采用C2 ,但是在windows机器上始终会采用C1,可以启动时候加上-client或者-server来强制指定。

你可能感兴趣的:(java,优化,String,Class,interface,compiler)