JVM内存模型
线程共享:堆、方法区
线程隔离:栈、本地方法栈、程序计数器
栈:用来放方法帧、局部变量等
堆:用来放对象
方法区:用放常量池、静态变量、类的字节码文件...
本地方法栈:用来放native方法
程序计数器:用来保存当前线程执行的位置
JVM三大厂商:
sun - Hotspot
Oracle - JRockit
IBM - J9
方法区是否属于堆?
理论上,方法区和堆在物理内存上是连在一起的,可以说是堆的一部分。
什么是元空间?
JDK1.8之后,永久代(方法区)被HotspotVM移除,替换成元空间(MetaSpace)。
元空间和永久代最大的区别,在于元空间可以直接使用物理内存。
GC垃圾回收算法种类
gc解决了3个问题:1 哪些对象应该被回收,2 什么时候回收,3 采用什么方式回收
然后最重要的就是第一点:有一些简单算法1 引用计数算法(方法效率最高,但是无法解决对象相互循环引用的问题) 原理就是对象有一个引用就+1,删除一个引用就-1,我们只计算引用为0的对象
2 根搜索算法 JVM一般会采用根搜索算法 它的处理方式是设立若干种根对象,当任何一个根对象都到达不了某个对象时,次对象就可以被回收
以上能解决那些对象可以被回收,在根搜索算法的基础上,而搜集垃圾的算法主要有2中:标记/清除算法,复制算法,标记/整理算法
标记/清除算法:首先标记不需要被回收的对象,标记完成掉统一回收未标记的对象(产生大量不连续的内存碎片)
复制算法:可将内存按容量大小分为相等的2块,每次只使用其中一块,当这一块内存用完了,就把活着的对象复制到另外一块上面,再把这用掉的这一块一次性处理了(这样内存只能使用一半了啊)
标记/整理算法:标记不需要被回收的对象,将标记的对象按照内存地址依次排列,然后将末端的内存地址以后的内存一次性回收
JVM的垃圾回收算法:分代收集算法
1、新创建的对象a,首先会进入E区。
2、如果触发了一次gc,这次gc没有清除掉这个a对象,则a对象会进入到S区(对象年龄涨了1岁,有可能是S1区,也可能是S2区),绝大部分对象都会死在E区里面。
3、两块S区完全一样,总之有一块S区一定是空的。如果又有一次GC,对象在S区中,还是没有被移除,则会复制到另一块S区。(复制-整理算法)
4、当一个对象的年龄达到15次(默认值)后,这是对象就会进入老年代。老年代的比例比新生代更大,而且GC一般不会扫描老年代。如果老年代空间不够,GC才会触发进行一次扫描(扫描老年代的GC成为major GC)
GC的分类:
young GC(minjor GC):只会扫描新生代,也是最频繁的GC
major GC:会扫描新生代、老年代
full GC:会扫描新生、老年、永久代
方法区是否属于堆?理论上方法区算是堆的一部分,但是为什么我们要单独挂出来方法区?
一般面试问堆和方法区多一些:
堆分为:新生代,老年的(1:2的比值,新生代和老年代的比值):
GC垃圾回收机制是作用子新生代的
JVM优化:
1、通过JDK的监控程序(jvisualvm),监控当前JVM的内存分布、占用以及GC的触发情况
2、定时打印堆内存的占用日志
3、根据内存的占比和gc触发的频率,通过调整JVM的参数进行相应的优化。