我们先了解一下JAVA的一些概念:
1. JVM:是指JAVA虚拟机,用于提供java解释环境,形成可执行文件。不同平台的JVM各有不同,但均提供相同的接口。
2. JRE:即JAVA运行环境。
3. JDK:核心开发包,提供java编译器、运行相关的环境、工具和类库。
4. 编译型语言和解释型语言:
JAVA程序的运行原理:
1. 源文件(.java源代码)通过编译器编译成字节码文件class。
2. 通过JVM中的解释器将字节码文件生成对应的可执行文件,运行。
3. 将编译后的程序加载到方法区,存储类信息。
4. 运行时,JVM创建线程来执行代码,在虚拟机栈和程序计数器分配独占的空间。根据方法区里的指令码,在虚拟机栈对线程进行操作,程序计数器保存线程代码执行到哪个位置。
“一处编写,处处运行”:编译后,不依赖于平台环境,在各种操作系统均可运行。
Class字节码文件:是一个二进制文件,包含了JAVA程序执行的字节码,包含的信息有版本、访问标志、常量池、当前类、超级类、接口、字段、方法、属性等,中间没有任何分隔符,文件开头有一个特殊标志,用16进制表示为0xcafebabe。
Class文件反编译后,可通过“JVM指令码表”查看指令,这些指令运行时都保存在方法区。
从指令码中看出,没有定义构造函数时,会有隐式的无参构造函数;方法参数保存在虚拟机栈里的本地变量表,每一个main方法都有一个String数组参数,保存在本地变量表的变量0。
JVM运行时数据区:包含线程共享部分和线程独占部分。
线程共享:线程共同访问的内存数据空间,随着JVM(虚拟机)或者GC(垃圾回收)而创建和销毁。包含方法区和堆内存。
1、方法区:JVM用来存储加载的类信息、常量、静态变量、编译后的代码等数据。在JVM规范中,这是一个逻辑区,根据不同的虚拟机有不同的具体实现,如oracle的HotSpot的方法区,在java7中放在永久代,java8中放在元数据空间,并通过GC机制对这个区域进行管理。目前有三大Java虚拟机:HotSpot,oracle JRockit,IBM J9。
2、堆内存:存放对象的实例,在JVM启动时创建。可细分为老年代、新生代,垃圾回收器主要就是管理堆内存,如果满了就会出现OOM(OutOfMemoryError)。
线程独占:每个线程都会有自己独立的空间,随着线程的生命周期而创建和销毁。包含虚拟机栈、本地方法栈、程序计数器。
1、虚拟机栈:即虚拟机执行JAVA代码的栈,每个线程都会在这有一个私有空间。线程栈由多个栈帧(Stack Frame)组成,一个线程会执行一个或多个方法,一个方法对应一个栈帧。栈帧内容包括:局部变量表、操作数栈、动态链接、方法返回地址、附加信息等。栈内存默认最大是1M,超出则抛StackOverflowError。
2、本地方法栈:即虚拟机执行Native本地方法的栈,和虚拟机栈的主要区别是执行的方法不同。在虚拟机规范没有规定具体的实现,由不同的虚拟机厂商去实现。HotSpot虚拟机中虚拟机栈和本地方法栈的实现方式是一样的,超出大小后也会抛出StackOverflowError。
3、程序计数器:记录当前线程执行字节码的位置,存储的是字节码指定地址,如果执行Native方法,则计数器值为空。每个线程在这都有一个私有空间,占用很少的内存空间。
CPU同一时间只会执行一条线程中的指令,JVM多线程会轮流切换并分配CPU执行时间,在线程切换后,需要通过程序计数器来回复正确的执行位置。
------------顺带记录一下相关指令----------
1. 编译:javac Demo1.java
2. 执行:java Demo1
3. 反编译 javap –c Demo1.class