- JVM的组成:(使用class loader 进行类加载)
- 方法区:
- 存放类的信息、常量、静态变量等存放的地方
- 线程共享
- 有时会成为永久代,少量的垃圾回收
- 运行时常量池
- JAVA栈:服务于java方法,
- 局部变量(方法内变量)
- 操作数栈:存放运算的结果及操作数
- 动态链接
- 线程私有,生命周期与线程一样
- 本地方法栈:与方法栈类似,native(调用非java代码的接口)方法工作区
- 堆:被所有线程共享,几乎所有实例在内存开辟空间的地方,经常GC(垃圾回收)
- 程序计数器:解释字节码指令时,依赖计数器的顺序,异常、循环、跳出等逻辑功能都需要计数器,占用内存小
- 方法区:
2.java加载类的过程的步骤
2.1 加载
分三步
2.1.1 根据类的全限定名 获取 二进制流
2.1.2 把二进制流的静态存储数据结构转换成 运行时数据结构
2.1.3 内存中生成类对象作为类的访问入口
2.2 验证
主要是保证类的代码不会危害到虚拟机
2.2.1 文件格式验证
2.2.2 元数据验证
2.2.3 字节码验证:确定程序语义正确
2.2.4 符号引用验证 :解析过程中用到
2.2.5 准备:初始化 类的静态变量 分配内存及默认值-方法区,这个阶段是不会分配实例变量的内存,其在对象实例化时与对象一起存放在堆中。
2.3 解析
将 符号引用 转换成 直接引用 , 注:不一定是 在初始化之前,也有可能之后
2.4 初始化
执行类中JAVA程序代码,前面的阶段都由JVM主导和控制,除非使用自定义类加载器
3.Java中的垃圾回收的方法有哪些?
(1)标记-清除 :标记不可达的对象,最后一并清除。
(2)标记-压缩、整理:标记清除会产生内存碎片,故将存活的对象向一端压缩。
(3)复制算法:内存区域被分成2块,一块用完了,将存活的对象复制到另一个区域,清除当前区域的内容。
(4)引用计数法:将不能被引用的对象回收
(5)分代回收:内存中的对象按存活时间分成了年轻代、老年代,年轻代使用复制算法,老年代使用标记-压缩算法。
4.如何判断一个对象是否存活?
可达性算法 :一个对象若无法从程序的根对象访问到,视为不可达,回收
引用计数法:记录对象被引用的次数,当为0时回收
5.什么是类加载器,以及类加载器的种类:
1.启动加载器(核心类库)(Bootstrap ClassLoader)用来加载 java 核心类库,无法被java程序直接引用
2.扩展加载器(扩展类库)(extensions class loader):它用来加载 Java 的扩展库
3.系统类加载器(应用类库)system class loader 根据类路径CLASSPATH
4.自定义加载器
6.java内存分配和回收策略以及minorGCorFULLGC(majorGC)
内存分配:
(1)栈:本地方法栈和虚拟机栈
(2)堆:被所有线程共享,gc主要区域,分为年轻代和老年代,年轻代分为eden区,存放新创建的对象, From survivor 和 To survivor 保存 gc 后幸存下的对象,默认 情况下各自占比 8:1:1
,大的对象直接老年代
(3)方法区:存放类的信息,常量,静态变量,习惯叫永久代
(4)程序计数器:逻辑处理的控制组件,线程私有
回收策略:
对象优先在堆的eden区分配,存放新创建的对象minorGC频率高,大的对象直接老年代,存活时间长的老年代 fullgc/ majorGC,为提高效率,可在majorGC之前做minorGC
回收策略以及 Minor GC 和 Major GC:
1) 对象优先在堆的 Eden 区分配。
2) 大对象直接进入老年代。
3) 长期存活的对象将直接进入老年代。
当 Eden 区没有足够的空间进行分配时,虚拟机会执行一次 Minor GC.Minor GC 通常发生在 新生代的 Eden 区,在这个区的对象生存期短,往往发生 GC 的频率较高,回收速度快。
Major GC 发生在老年代,一般情况下,触发老年代 GC 的时候不会触发 Minor GC,但是 通过配置,可以在 Full GC 之前进行一次 Minor GC 这样可以加快老年代的回收