执行流程图
第一步:JVM申请内存
堆30m,元空间30m,(隐藏)虚拟机栈1m等。此内存向操作系统申请。
第二步:初始化运行时数据区
当JVM启动时,方法区和堆先出来。因为此两个区域与运行无关。虚拟机栈当运行需要时申请。
第三步:类加载
(1)此时我们程序中自己写的类(JVMObject.class,Teacher.class),以及jre自带(Math.class)的类开始加载进入方法区
(2)静态变量与常量也会进入方法区(MAN_TYPE,WOMAN_TYPE)
第四步:执行方法
当JVM启动时会启动一个线程(俗称主线程)。同时也会申请一个虚拟机栈。此时main()方法进栈。
第五步:创建对象
当遇到Teacher t1 = new Teacher()时,new Teacher()进堆,t1进虚拟机栈。当遇到Teacher t2= new Teacher()时,再次生成new Teacher()进堆,t2进虚拟机栈。
GC概念
Java中GC会自动回收堆中的垃圾
可以主动触发垃圾回收:System.gc(),非常影响性能,不推荐
内存可视化工具HSDB
HSDB,jdk下的一个检测jvm运行时的可视化工具。
堆信息: 可以通过工具查看对象的地址
栈信息: 可以查看栈帧的局部变量表
JVM对栈的优化技术
当形参(局部变量表)和实参(操作数栈)进行值传递时,这个实参和形参都共用一个内存地址,节约空间。
常量池与字符串
常量池----------虚拟机规范的一个区域(在写方法区的时候必须去写这个部分)
Class(静态)常量池
Class里面的东西(接口,方法,版本,字面量)??????????
字面量
什么是字面量?这东西一开始先保存在方法区,然后再根据String或者int分配到栈或者方法区么?
String a =”123”; String的字面量
Int a =123; int的字面量
符号引用 ??????????
在Person类中引用Tools类
编译的时候,tools真实内存地址
Org.king.Tools ---符号引用
类加载的时候---符号引用---真实引用
运行常量池
直接引用放在运行时常量池。(根本没明白!!!!)JDK1.7以后可以放在堆里。但逻辑上还是在方法区(完全不懂)
字符串常量池
不知道是属于运行常量池还是独立出来,但这个东西就是为了存放String类型的数据的。
String类是final。Value也是final。不能被重写,数据不能被修改,所以String都存放在字符串常量池。为什么这么设计?
- 安全
- Hash唯一 hashmap key-value