Class 文件内容?
Class文件包含Java执行的字节码,数据是严格按照“Jvm规定的格式”排列的二进制流。
文件头是:ca fe ba be(16进制咖啡宝贝)
通过java-p class可以看到:
主/次版本号: version52: //版本号规则:JDK5,6,7,8 分别对应 49,50,51,52
访问标识: flags:ACC_PUBLIC,ACC_SUPER //对应一些访问的权限。
常量池:Constant pool : 类信息包含的静态常量(类名称引用、方法名称引用、类本身用到的常量、自己创建的),编译后就可以确定。
构造方法,main方法:可以看到方法被编译成了一条条的jvm执行指令。
Class加载后jvm运行时数据区?1:线程共享部分:
A、方法区
I、虚拟机规范中,方法区是一个逻辑区域,具体实现因虚拟机而异。
II、存放类信息、常量、编译后的代码、【静态变量(1.7移到了堆)】 。
III、版本1.7时方法区在永久代中。版本1.8方法区在元数据空间中,并通过GC管理。
IIII、方法区中有个区域叫做:“运行时常量池”。作用是将代码中的常量单独存放。
B、堆内存
I、JVM启动时创建,存放对象实例。GC主要管理区域(垃圾堆)。会抛出:OutOfMemroyError。
II、老年代(Old)。
III、新生代 (Eden、So、S1三部分)。2:线程独占部分:
A、虚拟机栈
I、线程独占(每个线程都从虚拟机栈空间中划分出一部分独立空间单独运行),每个线程有多个栈帧,每个栈帧相当于线程中执行的一个方法。
II、栈帧中包含:局部变量表、操作数栈、动态链接、方法返回地址、等。
III、默认大小是 1M ,超出后抛出StackOverflowError。
IIII、方法依次调用的过程中,栈帧会不断压栈弹栈。
B、本地方法栈
I、本地方法栈是为了执行Native本地方法而准备的。
II、没有规范实现方式、不同的虚拟机厂商有不同的实现,HotSpot虚拟机实现方法和虚拟机栈实现类似。
C、程序计数器
I、记录字节码执行的位置,存储的是字节码中指令的地址,如果是执行Native方法则为null
II、多线程切换时方便恢复正确的线程执行位置。
程序运行流程?1编译: 源代码编译成字节码文件。2加载: 所有相关的Class都被加载到方法区,Class中的常量加载到 “运行时常量池”3运行:JVM会创建线程并为线程分配:虚拟机栈、本地方法栈、程序计数器
接下来:虚拟机栈、本地方法栈中:栈帧不断的压栈弹栈(对印着方法的调用)。
程序计数器记录“字节码命令”执行的地址。
其中每个栈帧中包含(方法内部命令执行时用。用于:加载值保存值运算值):
I、本地变量表
II、操作数栈
Jvm运行时数据区详细?
“Java源代码”编译生成“.class字节码”
class加载到JVM中,JVM给class分配不同数据区用于存储不同的数据。
数据区是逻辑分区,不同的虚拟机有不同的实现。
方法区:
存放类型信息:1、类信息:类的名称、修饰符、超类、接口等、常量、【静态变量(1.7移到了堆)】。2、已加载类信息:字段信息、方法信息、该类的装载器引用、clas实例的引用等。
Oracle 的HotSpot虚拟机:1、 java1.7之前,方法区位于永久代(PermGen),永久代和堆相互隔离,永久代的大小在启动JVM时可以设置一个固定值,不可变。2、 java1.7中,static变量从永久代移到堆中。3、 java1.8中,取消永久代,方法存放于元数据空间(Metaspace),并通过GC管理,元数据空间仍然与堆不相连,但与堆共享物理内存,逻辑上可认为在堆中。
堆内存:
存放对象,Jvm启动时创建,GC管理的主要区域,如果满了就会OutOfMemroyError,Java堆中还可以细分为:“新生代”和“老年代”;
Java堆是垃圾收集器管理的主要区域,因此很多时候也被称为”GC堆”(Garbage Collected Heap,幸好国内没有翻译成”垃圾堆”).
从内存回收的角度来看,由于现在收集器基本都采用分代收集算法,所以Java堆中还可以细分为:“新生代”和“老年代”;
根据Java虚拟机规范的规定,Java堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可,就像我们的磁盘空间一样.在实现时,既可以实现固定大小的,
也可以是可扩展的,不过当前主流的虚拟机都是按照可扩展来实现的(通过-Xmx和-Xms控制).如果在堆中没有内存完成实例分配,并且堆也无法再扩展时,就会抛出OutOfMemoryError异常。
虚拟机栈:
java方法执行的内存模型,线程隔离的(线程之间相互隔离)
方法调用时,创建栈帧,并压入虚拟机栈;方法执行完毕,栈帧出栈并被销毁
每个java方法在执行时,会创建一个“栈帧(stack frame)”
栈帧的结构分为“局部变量表、操作数栈、动态链接、方法出口”几个部分(这里只需要了解栈帧是一个方法执行时所需要数据的结构)。
我们常说的“堆内存、栈内存”中的“栈内存”指的便是虚拟机栈,确切地说,指的是虚拟机栈的栈帧中的局部变量表,因为这里存放了一个方法的所有局部变量。
虚拟机栈最大默认内存时1M,超出会报StackOverflowError。
本地方法栈:
Native方法执行的内存模型,线程隔离的。
虚拟机规范没有具体的实现,由不同的厂商实现,Oracle 的HotSpot中本次方法栈和虚拟机栈的实现时类似的实现。
程序计数器:
记录当前执行的字节码的位置。存储的是字节码指令地址,如果是Native方法则为空。线程隔离。
多线程中记录某一个线程的执行进度。方便在线程切换后恢复执行位置。