1.什么是JVM?
Java文件à字节码(.class file)à虚拟机加载.class文件,翻译成0101码àjvm在Windows和linux的版本不同(还是平台有关的,可移植性有jvm实现)
JVM的功能
-软件层面的翻译,映射了人可以认知的代码,即class文件到机器指令
-内存管理,可以让人专注于业务代码(对比c++,要申请释放空间,java帮我们做了这件事,内存管理)
JVM学习的必要:
内存管理中内存泄露溢出的时候要了解jvm
2.运行时数据区
为什么要讲运行时数据区:描述了java代码在运行时的状态
分区:数据 指令
数据:方法区heap
程序计数器:当前线程正在执行的字节码的地址 行号(为什么要记录下来当前指令?因为CPU执行线程通过时间片,线程可能被抢占挂起,当前的指令不一定可以执行完成,所以要保存下来)
虚拟机栈:存储当前线程运行方法所需要的指令,数据,返回地址
进出虚拟机栈的最小单元叫栈帧(主要是局部变量,操作数栈,动态,出口)
本地方法栈
方法区: 类信息,常量,静态变量,JIT(即时编译,动态代理,动态生成类的时候会生成class文件加载到jvm中)(静态变量以及常量为什么存储在堆中?)
Heap:内存模型JMM
三代(新生代,老年代,永久代)
为什么分为三代?:
Metaspace规避了永久代会溢出的问题,可以自己动态扩容。不属于堆。它的不足是无限扩容,堆外内存太大。所以需要对其进行管制,定义metaspace的大小。
新生代为什么是8:1:1?新生代里的回收算法是复制回收算法(把空间分为2块,一块分配空间使用,另一块不分配。回收时将无法删除的放入另一块,其他的删除。)实践出真知 ,通过统计学,对象的生命周期不同,用分代方式分配空间。而98%的对象,在一次minor gc的过程中就会被回收,不能回收就放到s1。所以分为811,可以利用的空间就有90%。Eden8M,s01M中一次minor gc后存活的对象基本都会被放到s1M。
如果s1放不下,分配担保,老年代给出空间。
新生代与老年代是1:2
什么样的对象应当被GC?
-判断算法:引用计数法(循环引用,A引用B,B引用A,计数不是0是1,所以jvm没有使用引用计数法),可达性分析(GCroot指向A,A指向B)
如果从GCRoot可以有路径到达,则不回收,若有独立的节点,如C则,回收。
哪些可以成为GCroot?
为什么可以成为GCroot?因为在GC的时候,线程在运行某个方法,所有变量都不被回收。而GCRoot本身要求自己不会被回收,所以可以做GCroot。
不可达是不是一定会被回收?新生代与老年代有交叉。不是,finalize()可以在下次GC之前进行挽救(使用GCroot指向将回收的节点)
静态变量如何回收?静态变量在方法区。
运行方法时要压栈,(可能调用多次方法栈)