一、简单概述:
一个java程序的执行流程可以简单的分为以下几个步骤:1.编辑源代码--->2.编译阶段,生成.class文件,即源文件有编译器编译成字节码文件--->3.类加载器加载字节码文件--->4.虚拟机加载运行。下面就对这几个阶段进行一个简单的解析。若有错误,欢迎指正!
JVM(java虚拟机)执行过程:加载 -> 合法性和安全性检测 -> 解释执行(循环直到程序执行完毕),JVM將字节码转换成各种平台上的机械代码。
二、简单解析:
编辑源代码阶段:编辑编辑源代码就是在任何一个工具上编写源代码,最后生成一个.java文件,这就是我们程序员的日常工作之一,也是最简单的工作之一。编译源文件生成.class文件
编译阶段:创建完源文件之后,程序先要被JVM中的java编译器进行编译为.class文件。java编译一个类时,如果这个类所依赖的类还没有被编译,编译器会自动的先编译这个所依赖的类,然后引用。如果java编译器在指定的目录下找不到该类所依赖的类的 .class文件或者 .java源文件,就会报"Cant found sysbol"的异常错误。编译后的字节码文件格式主要分为两部分:常量池和方法字节码。常量池记录的是代码出现过的(常量、类名、成员变量等)以及符号引用(类引用、方法引用,成员变量引用等);方法字节码中放的是各个方法的字节码。
加载字节码文件:*.java文件经过javac编译后得到*.class文件,称为字节码文件,*.Class文件是一组以8字节为基础单位的二进制流,各个数据项目按照严格的顺序排列在class文件中,中间没有任何的分隔符,这使得class文件在存储的内容全部是虚拟机运行程序所必须的,当存储的数据大于8位就采用大端模式。class文件不像xml等语言有分隔符,所以各种数据类型的排列顺序还是数量都是严格的。那么在这里我们就要好好谈谈虚拟机的加载机制了。在class文件中的各种信息,最终都要加载到虚拟机中才能运行和使用,但是虚拟机如何加载这些class文件? (虚拟机的类加载机制,虚拟机把描述类的数据从class文件加载到内存,并对数据进行效验,转换解析和初始化,最终形成可以被虚拟机直接使用的java类型。java类运行的过程大概分为两个步骤:(1)类的加载 (2)类的执行。需要说明的一点的是:JVM主要在程序第一次运行时主动使用类的时候,才会立即去加载。换言之,JVM并不是在运行时就会把所有使用到的类都加载到内存中,而是用到,不得不加载的时候,才加载进来,而且只加载一次!根据上面的程序,详解该程序运行的详细步骤:(1)在类路径下找到编译好的 java 程序中得到 Test.class 字节码文件后,在命令行上敲 java Test,系统就会启动一个 JVM 进程,JVM进程从classpath路径下找到一个名为Test.class的二进制文件,将Test.class文件中的类信息加载到运行时数据区的方法区中,这一过程叫做类的加载。(只有类信息在方法区
中,才能创建对象,使用类中的成员变量);(2)JVM 找到main方法的主函数入口, 持有一个指向当前类(Test)常量池的指针,而常量池中的第一项是发现是一个对Animal对象的符号引用,并且main方法中第一条指令是Animal animal = new Animal("super_yc"),就是让JVM创建一个Animal对象,但是方法区中还没有Animal类的类信息,于是JVM就要马上的加载Animal类,将Animal类信息放入到方法区中,于是JVM 以一个直接指向方法区 Animal类的指针替换了常量池中第一项的符号引用;(3)加载完Animal类的信息以后,JVM虚拟机就会在堆内存中为一个Animal类实例分配内存,然后调用其构造函数初始化Animal实例,这个实例持有指向方法区的Animal类的类型信息(其中包含有方发表,java动态绑定的底层实现)的引用。(animal指向了Animal对象的引用会自动的放在栈中,字符串常量"super_yc"会自动的放在方法区的常量池中,对象会自动的放入堆区)
(4)当使用 animal.pringName()的时候,JVM根据栈中animal引用找到Animal对象,然后根据Animal对象持有的引用定位到方法区中Animal类的类型信息方法表,获得pringName()函数的字节码地址,然后开始运行函数。