Java运行时内存划分与垃圾回收--以及类加载机制基础

时间:2024-01-01 08:28:51

----JVM运行时内存划分----不同的区域存储的内容不同,职责因为不同
1.方法区:被线程共享,存储被JVM加载的类的信息,常量,静态变量等
2.运行时常量池:属于方法区的一部分,存放编译时期产生的字面量和符号引用
3.Java堆区:被线程共享,主要存放new出的对象,GC主要负责的区域
4.虚拟机栈:属于线程私有,存放方法中的参数局部变量等
5.本地方法栈:线程私有,存储与本地方法相关的变量
6.PC,程序计数器线程私有,用来记录当前以及下次要执行的指令
----对象访问的方式----
1.句柄:对象的引用指向一个句柄,句柄再指向堆中对象实体/方法
2.直接指针:对象的引用直接指向对象实体,通过实体指向对象的方法
----GC垃圾回收原理相关----
涉及到垃圾回收就要确定3个问题
1.那些对象需要回收?
即判断对象是活着与否--常见的算法
* 引用计数法:计数器,简单但是对于相互引用的对象无法进行判断
* 根搜素法:现在基本使用的是这个,算法思路:通过设置一些对象为根对象,通过
引用不断的向下查询,若某个对象不存在从根对象的路径,就可能被回收。
如何定义根对象?
* 虚拟机栈中的引用对象
* 方法区中类的静态引用对象
* 常量引用对象
* 本地方法引用对象
对于特殊对象处理:在内存足够时保留,不够用的时候回收。
对于这类对象如何坚定--出现了对引用的更细的划分
* 强引用:大部分对象都是
* 软引用:对象有用但是非必须
* 弱引用:对象非必须
* 虚引用:没办法通过引用操作,只是为了在回收的时候给系统通知
2.什么时候回收?
GCroots无法找到--先标记筛选(根据是否有必要执行finalize())
若没必要则不回收,反之则将其加入一个等待被回收的队列中,等待
被回收,此期间若是有引用指向该对象,就将该对象移除该队列,反之
该对象就被将回收
3.如何进行对象的回收?--根据不同的回收算法
* 标记-清除:先标记在清除,效率低且容易产生大量的小的不连续的空间
* 复制法:将内存划分两块,标记完后,将活的对象复制到新的区域,在将
原来标记的对象清除
* 标记-整理:先标记,在清除,然后将活着的对象整理,创造出连续的区域
* 分代-收集:将堆内存划分为新生代和老年代,不同的区域采取不同的回收算法
新生代采用复制法,老年代采用的是标记-整理
注意:回收方法区:虽然垃圾不多但是也存在垃圾回收
废弃常量:依据的是否有引用指向
无用的类回收需要满足3个条件
* 所有的实例被回收
* 加载该类的ClassLoader对象被回收
* 该类的Class对象无引用指向,不可以使用反射获取类
----具体的垃圾回收器-----
不同的虚拟机厂商使用不同的垃圾回收器,存在有并行和并发的垃圾回收器
并行:垃圾回收线程在执行的时候,用户线程需要等待
并发:垃圾回收器和用户线程的执行相互交替--通过CPU的调度
----对象分配策略----
1.优先分配在堆的新生代区
2.大对象进入老年代区
3.长期存活的对象分配的老年代区(通过给对象设置年龄判断其是否长期存活)
----虚拟机执行子该过程---
1.类文件的结构
是一个二进制的字节流(无符号数+表组成)
其里面包含不同的属性表集合--这些就是该类的所有信息
2.虚拟机加载机制
虚拟机将描述类的class文件加载金内存并对其进行解析最后形成JVM可以
使用的Java类型。类加载的时机--运行时期
类加载的过程:加载-(验证-准备-解析)-初始化
* 加载:根据类名获取二进制字节流--解析成JVM识别的类型--在堆中产生一个
封装该类字节码文件的Class对象
* 验证:确定当前字节码文件的信息与虚拟机信息符合,并且不会对虚拟机
造成不安全的影响
* 准备阶段:为类变量分配内存并设置默认值
* 解析:字段解析/类静态方法解析/接口方法解析
* 初始化:进行指定的初始化
类加载器--完全类加载的工作
不同的类有不同的类加载器--用来唯一确定一个类的存在
类加载器的分类:
* 启动类加载器:属于JVM的一部分,C++实现
* 其他类加载器:利用实现Java中抽象类ClassLoader,独立于JVM
* 自定义类加载器:就是通过实现已有的抽象类/接口
双亲委派加载机制:一个类加载器收到类加载请求后将其传给其父类加载器
直到类加载器的顶层,顶层处理、交给子类处理加载请求
类加载器的层次结构
* 自定义类加载器--应用程序类加载器--扩展类加载器--启动类加载器
java.lang.reflection里面封装了类文件中字段和方法--Fields,Methods
Class-封装的是类的字节码文件
ClassLoader类--是封装的是类加载机制
3.虚拟机字节码执行引擎
运行时栈帧--其实就是某个方法在运行时候占用的虚拟机栈空间
栈帧包含:局部变量表/操作数栈/动态连接/方法的返回地址
方法在调用时候栈帧进栈,运行结束栈帧出栈
只有在栈顶的栈帧才可以被虚拟机执行引擎执行