java程序的执行流程
java支持平台无关性。而java平台由java虚拟机和java核心类所构成,正是虚拟机,它号称”一次编译到处运行“。
java源文件(*.java)--------> java编译器--------->字节码问件(*.class)--------> 类装载器------->字节码校验器--------->操作系统(window,linux等)。
java虚拟机的生命周期:
java虚拟机的天职:运行java程序。(装载class文件并且执行其中的字节码)
虚拟机实例诞生:启动一个java程序。(调用某个初始类的main()方法)
虚拟机消亡:程序关闭退出。
注意:如果一台计算机同时运行两个java程序,将得到两个虚拟机实例,每个java程序都运于它自己的java虚拟机实例中。
在java虚拟机内部有两种线程:守护线程 和 非守护线程。
守护线程:通常是有虚拟机自己使用的,如:执行垃圾收集任务。java程序可以把它创建的任何线程标记为守护线程。
非守护线程:有非守护线程在运行,那么这个java程序就运行。当该程序中所有的非守护线程都终止时,虚拟机实例将自动退出。加假如安全管理器允许,程序本身也能通过调用Runtime类或者System类的exit()方法来退出。
java虚拟机的体系结构:
每个java虚拟机都有一个类装载子系统:它根据给定的全限定名来装入类型(类 或 接口)。
每个java虚拟机都有一个执行引擎:它负责执行那些包含在被装载类的方法中的指令。
如图:
当java虚拟机运行一个程序时,它需要内存来存储许多东西,例如:字节码,已装载的class文件中得到的其他信息,程序创建的对象,传递给方法的参数,返回值,局部变量,等。java虚拟机把这些东西都组织到几个”运行时数据区“中,以便管理。
某些运行时数据区是有程序中所有线程共享,还有一些则只能由一个线程拥有。每个java虚拟机实例都有一个方法区及一个堆,它们都是由该虚拟机实例中所有的线程共享的。当虚拟机装载一个class文件时,他会从这个class文件包含的二进制数据中解析类型信息。然后把这些类型信息放到方法区中,当程序运行时,虚拟机会把所有的该程序运行时创建的对象都放到堆中。
由于java虚拟机并不知道某个class文件是如何被创建的,是否被篡改一无所知,所以它实现了一个class文件检测器,确保class文件中定义的类型可以安全的使用,class文件检验器通过四趟独立的扫描来保证程序的健壮性:1. class文件结构检查。 2. 类型数据的语义检查。 3字节码验证。 4. 符号引用验证。
java虚拟机再执行字节码时还进行其它的一些内置的安全机制的操作,他们作为java编程语言保证java程序健壮性的特性,同时也是java虚拟机的特性:1. 类型安全的引用转换。2. 结构化的内存访问。 3.自动垃圾收集。 4.数组边界检查。 5.空引用检查。
java虚拟机的数据类型:
java虚拟机是通过某些数据类型来执行计算的,数据类型可以分为两种:基本数据类型 和 引用数据类型,基本类型的变量持有原始值,而引用类型的变量持有引用值。
但boolean有点特别,当编译器把java源码编译为字节码时,它会用int或者byte表示boolean。在虚拟机中,false是由0表示,true则由所有非0整数表示。和java语言一样,java虚拟机的基本类型的值域在任何地方都是一致的,不管主机平台是什么,一个long在任何虚拟机中总是一个二进制补码的有符号整数。
对于returnAddress,这个基本类型被用来实现java程序中的finally子句,java程序员不能使用这个类型,它的值指向一条虚拟机指令的操作码。
程序计数器:
对于一个运行中的java程序而言,每一个线程都有它的程序计数器。程序计数器也叫PC寄存器。程序计数器既能持有一个本地指针,也能持有一个returnAddress。当线程执行某个java方法时,程序计数器的值总是下一条被执行指令的地址。这里的地址可以是一个本地指针,也可以是方法字节码中相对该该方法起始指令的偏移量。如果该线程正在执行一个本地方法,那么此时程序计数器的值是undefined。
该篇博客为提高自身对 java虚拟机 的了解所记录。内容来自各博友。如雷同:为借鉴谢谢。