1,内存模型
方法区:线程共享,存储类信息、常量、静态变量、即时编译器变异后的代码,这里也会发生GC(针对方法区里的常量池和对类型的卸载)
堆:线程共享,创建的对象和数组都保存在这里,垃圾回收的地方
虚拟机栈:线程私有,用于存储局部变量表(基本类型、对象引用),操作数栈(运算结果、运算的操作数),动态链接(将常量池中的符号引用在运行期转化为直接引用)
本地方法栈:线程私有,与虚拟机栈类似,只不过为native方法服务
程序计数器:线程私有,当前线程所执行的字节码的行号指示器,没有oom的区域。
栈帧:可以理解为栈上的一块内存区域,保存了没一次函数调用涉及的相关信息,一般包括:函数的返回地址和参数,临时变量,函数调用的上下文
堆:
2,GC
新生代
用来存放新生的对象,又分为Eden区,ServivorFrom区,ServivorTo区
Eden区:小对象出生的地方(大对象直接分配到老年代),Eden区内存不够时触发MinorGC
ServivorFrom:上一次GC的幸存者,作为本次GC的被扫描者
ServivorTo:本次GC的幸存者
ServivorFrom和ServivorTo在每次GC后互换身份
MinorGC:
采用复制算法
步骤:
1,将Eden和ServivorFrom中存活的对象复制到ServivorTo中(如果对象年龄达到老年标准15次,则复制到老年代),同时把这些对象的年龄加1
2,清空Eden和ServivorFrom中的对象
3,ServivorFrom和ServivorTo互换
老年代
元空间
不再虚拟机中,使用的是本地内存,存放元数据
垃圾回收与算法:
如何确定垃圾:
1,引用计数法
2,可达性分析,两次标记后都是不可达对象,才会面临回收
GC Root:栈中的引用,方法区中的静态引用,JNI中的引用
算法:
1,复制算法:
可用内存被压缩了一半
2,标记清除算法:
分两个阶段,标记和清除,内存碎片化严重
3,标记整理算法:
4,分区收集算法:
将整个堆空间划分为连续的 不同小区间,每个小区间独立使用,独立回收
垃圾收集器:
1,Serial:
单线程,复制算法,新生代,暂停工作线程
2,ParNew:
多线程,复制算法,新生代,暂停工作线程
3,Parallel Scavenge:
多线程,复制算法,新生代
4,Serial Old:
单线程,标记整理算法,老年代
5,Parallel Old:
多线程,标记整理算法,老年代
6,CMS:
多线程,标记清除算法
7,G1:
标记整理算法,区域划分和优先级区域回收机制
3,类加载机制
加载,验证,准备,解析,初始化
加载:
通过类的全限定名获取该类的二进制流,生成该类的class对象
通过类加载器完成
验证:
确保class文件的字节流中包含的信息符合当前虚拟机的要求
准备:
为类的静态变量分配内存(方法区中)并设置初始值
解析:
将符合引用替换为直接引用
初始化:
4,类加载器
通过类的全限定名获取该类的二进制字节流的代码块叫做类加载器
启动类加载器:JAVA_HOME\lib
扩展类加载器:JAVA_HOME\jre\lib\ext
应用程序类加载器:classpath:
5,双亲委派
当一个类收到了类的加载请求时,不会自己先去加载这个类,而是将其委派给父类去完成,当父加载器反馈无法完成这个请求的时候,子加载器才会尝试自己去加载。
目的:使用不同的类加载器时,保证同一个类只被加载一次