day04

ava整个编译以及运行的过程相当繁琐,我就举一个简单的例子说明:

编译原理简单过程:词法分析 --> 语法分析 --> 语义分析和中间代码生成 --> 优化 --> 目标代码生成

Java程序从源文件创建到程序运行要经过两大步骤:

1、Java文件会由编译器编译成class文件(字节码文件),会经过编译原理简单过程的前三步;

2、字节码由java虚拟机解释运行,解释执行即为目标代码生成并执行。因为java程序既要编译的同时也要经过JVM的解释运行,所以说Java被称为半解释语言!

( "semi-interpreted" language)

day04day04

 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class Main {       public static void main(String[] args) {         Animal animal = new Animal("Tom");         animal.printName();     }   }   class Animal{     private String name;       public Animal(String name) {         super();         this.name = name;     }           public void printName(){         System.out.println("Animal = " this.name);     } }

第一步(编译):创建完源文件之后,程序先要被JVM中的java编译器进行编译为.class文件。java编译一个类时,若这个类所依赖的类还没有被编译,编译器会自动的先编译这个所依赖的类,然后引用;若java编译器在指定的目录下找不到该类所依赖的类的 .class文件或者 .java源文件,就会报"Can't found sysbol"的异常错误。

 

编译后的字节码文件格式主要分为两部分:常量池和方法字节码

  常量池记录的是代码出现过的字面量(文本字符串、八种基本类型的值、被声明为final的常量等)以及符号引用(类和方法的全限定名、字段的名称和描述符、方法的名称和描述符);

  https://www.cnblogs.com/superyc/p/9975254.html

  方法字节码中放的是各个方法的字节码(依赖操作数栈和局部变量表,由JVM解释执行)

 

第二步(运行):java类运行的过程大概分为两个步骤:

(1)类的加载

  加载 --> 验证 --> 准备 --> 解析 --> 初始化(其中验证、准备、解析统称为类的连接);(参考《深入了解Java虚拟机》)

  加载:通过一个类的全限定名来获取定义此类的二进制字节流(Class文件);将这个二进制字节流所代表的静态存储结果转化为方法区的运行时数据结构;在内存中生成一个java.lang.Class对象,注意:存放在方法区!

  验证:验证目的是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全;使用纯粹的Java代码无法做到诸如访问数组边界意外的数据、将一个对象转型为它未实现的类型、跳转到不存在的代码之类的事情,如果这样做了,编译器将拒绝编译!

  准备:准备阶段是正式为类变量分配内存并设置类变量初始值的阶段,这些变量所使用的内存都将在方法区中进行分配。首先这时候进行内存分配的仅包括类变量(static修饰的变量),而不是实例变量,实例变量将会在对象实例化时随着对象一起分配在Java堆中。

1 public static int value = 123

  变量value在准备阶段过后的初始值为0而不是123,因为这时候尚未开始执行任何Java方法,在类初始化的时候才会将value的值赋为123.

  解析:解析阶段是虚拟机将class常量池内的符号引用替换为直接引用的过程。

     符号引用:符号引用以一组符号来描述所引用的目标,符号可以是任何形式的字面量,只要使用时能无歧义的定位到目标即可;

       直接引用:是直接指向目标的指针、相对偏移量或是一个能间接定位到目标的句柄。有了直接引用,那引用的目标必定已经在内存中存在。

  初始化:类初始化阶段是类加载过程的最后一步;在准备阶段,变量已经赋过一次系统要求的初始值,而在初始化阶段,则根据程序员通过程序制定的主观计划去初始化类变量和其他资源:初始化阶段是执行类构造器<clinit>( )方法的过程。

  <clinit>( )方法是由编译器自动收集类中的所有类变量的赋值动作和静态语句块(static { }块)中的语句合并产生的,编译器收集的顺序是由语句在源文件中出现的顺序所决定的

上一篇:C++学习Day04


下一篇:Adroid我还是个菜鸟——导入jar包