从java虚拟机底层理解java语言运行机制 001

类的加载、连接、初始化


一、先来讲讲java虚拟机和程序的生命周期:

在如下几种情况Java虚拟机会结束生命周期:

—执行System.exita() 方法

—程序正常之行结束

—程序在执行过程中遇到了异常或者错误而 异常终止

—操作系统出现错误而导致java虚拟机进程终止


二、类的加载、链接与初始化

1、加载:查找并且加载类的二进制数据到内存中

2、连接:

        —验证:确保被加载的类的正确性

        —准备:为类的静态变量分配内存,将其初始化为默认值。比如说,有一个类Person,代码如下:

                  

<pre name="code" class="java">class Person{
	//静态变量
	public static int value1=9;
	public static int value2=0;
	public static int value3;
	
	//一系列的方法
	public void method(){};


 

                       准备阶段就是为静态变量value1、value2、value3、分配内存,并且将它们设为默认值:0 。


                   —解释:将类中的符号引用转变为直接引用。在这里解释下符号引用和直接引用。比如说有如下的People类和car类:

Car:


<pre name="code" class="java">public class Car{
 //有一个方法run
 public void run(){
  System.out.println("car run");
 }


 
 


People:

<pre name="code" class="java">public class People{
	Car car;
	public void travel(){
             this.car.run();
	}
}


 
 

                                其中可以将代码块 this.car.run() 理解为为符号引用,在解析的过程中java虚拟机会将该符号引用转化为一个指向了Car 类的 run() 方法的指针


3、初始化:为类的静态变量赋予正确的初始值。就那刚才的person类来说,进行初始化的过程中才会将value1的值设置为9,value2的值设置为0,而value3的将保持为默认值:0.


好了,再举一个例子来说明类的家安在,链接与初始化的过程。假设有两个类,Singleton和一个含有主类的Test类。

Singleton:阅读代码的时候请注意一行被注释的代码

<pre name="code" class="java">public class Singleton {
	
	public static Singleton singleton=new Singleton();
	public static int value1=1;
	public static int value2=0;
	
	//public static Singleton singleton=new Singleton();
	
	private Singleton(){
		
		value1++;
		value2++;
		
	}
	
	public static Singleton getSingleton(){
		return singleton;
	}


 

主类:

<pre name="code" class="java">public class Test {

           public static void main(String[] args){
               Singleton s=Singleton.getSingleton();
               System.out.println("value1= "+s.value1);
               System.out.println("value2= "+s.value2);
            }

}


 

这时候的输出结果为:

value1 = 1

value2 = 0

在这里解释下程序的执行过程就知道该输出结果的由来。

根据之前的讲解,主方法调用了Sington这个类,于是java虚拟机会将Singleton.class文件加载到内存中,接着是执行验证操作。

接着是执行准备操作,由于静态代码块的顺序为:public static Singleton singleton=new Singleton();

                                                                                 public static int value1=1;

                                                                                 public static int value2=0;

程序底层的执行顺序为:1、为静态变量分配内存和初始值,即: public static Singleton singleton=null;

                                                                                                               public static int value1=0;

                                                                                                             public static int value2=0;

                                            2、执行静态代码块:

                                                 singleton=new Singleton();  ——>这一步会将value1的值变为1,value的值变为1  (执行Singleton的构造方法的封装好的操作)

                                              接着是执行      public static int value1=1;

                                                                public static int value2=0;

                                                                        (这两步是执行Singleton类中代码的第3和第4行)


        

所以最后的结果是 :

value1= 1

value2= 0




然后,我们将Singleton的一行代码:public static Singleton singleton=new Singleton(); 改变下顺序:将它放到静态变量的声明的后面:

public class Singleton {
	
	//public static Singleton singleton=new Singleton();
	public static int value1=1;
	public static int value2=0;
	
	public static Singleton singleton=new Singleton();
	
	private Singleton(){
		
		value1++;
		value2++;
		
	}
	
	public static Singleton getSingleton(){
		return singleton;
	}
	
	

}


继续运行主类,输出结果为:    value1= 2  

                                                   value2 =1

如果看明白了之前介绍的类的加载、链接与初始化的讲解的话应该能够明白这两个不一样的输出结果了。其实就是静态代码块的执行顺序不一样。



  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值