浅谈jvm
JVM即java虚拟机,是所有java程序运行必须的条件,是JRE(java运行环境)的中重要组成部分。
jvm有以下几个部分组成:
- 方法区,存放静态变量,常量,类的基本信息,常量池,是一个逻辑概念实际上是堆的一部分。
- 堆,存放具体的一些实例变量等等。
- 栈,存放引用信息。
- PC(程序计数器)
- 本地方法区,最早是为了实现c的内存操作。
下面主要讲讲堆。
我们通常所说的内存调优指的就是对堆的内存调优。
堆由下面三个部分组成:
- 新生代,由伊甸园区和两个幸存区。
- 老年区,该区里面的内存存活率比新生代要高一些。
- 永久区,里面包括方法区(又称为非堆),是一个逻辑空间,实际上不占虚拟机内存。
注:在Java8之后永久区就被更名为元空间。
我们在使用堆内存的时候,守护线程GC也在工作,它的工作方法具体有以下几种。
- GC之引用计数法,就是我们每次调用堆里面的内存的时候就会有一次计数。然后经过一段时间后就进行把一些不符合条件的垃圾内存清理,
- GC之复制算法,该算法会在两个幸存区之间多次复制,其中每次复制都会进行内存清理,并且每次复制的时候都会有from和to(空的内存区)区,这是对两个幸存区的逻辑名称。默认的,当我们的某些内存在经过15次复制仍然存活了下来,就会进入老年区。
缺点:浪费堆里面的幸存区一半内存
- GC之标记清楚法,这个方法分为两部实现,
- 扫描内存对象,对某些内存进行标记。
- 再次扫描,对没有标记的内存进行清除。
缺点:两次扫描,浪费时间,并且会产生内存碎片。
- GC之标记压缩法,该方法其实就是在上个标记清楚法之后再加一步,内存压缩,防止产生内存碎片。
- 再次扫描,向一端移动存活的内存对象。
缺点仍然是时间复杂度太高
GC方法分析
内存效率
复制算法> 标记清除法> 标记压缩法
内存利用率
标记压缩法=标记清除法> 复制算法
由于以上这些算法都有一些弊端,所以在我们实际应用中使用的是=分代收集算法=
- 对于年轻代来讲,他们的内存数据存活率低,对于空间的需求不是很大,所以我们使用的是复制算法。
- 对于老年代来讲,他们数据的存活率比较高,所以更适合用标记压缩清楚算法。
方法区的一些常识
另外,对于方法区而言
在程序启动的时候会以以下顺序存入数据:
- 静态代码块
- main线程启动
- 匿名代码块
- 构造器
- 一般数据