栈:
每一个栈有多个线程,每个线程有独立的方法栈。局部变量存在于栈中,栈里面是线程私有的。
方法调用就压栈,调用结束就出栈。
栈的特点是先进后出,当一个程序中main方法压栈执行,main方法中调用了A方法,那么A方法会压栈执行,A方法调用B方法,B方法压栈执行。当B方法执行结束后会从栈顶出栈。依次出栈A方法,main方法。
栈的空间不可能是无限的,所以我们会遇到栈空间溢出的情况。
本地方法栈(Native Stack):
与java虚拟机栈所发挥的作用非常相似,他们之间的区别在于虚拟机栈为虚拟机栈执行java方法(字节码)服务,而本地方法栈则为使用到native方法服务。
方法区:
与堆一样,是各个线程共享的内存区域, 它用于存储虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据。虽然java虚拟机规范把方法区描述为堆的一个逻辑部分,但是她确有一个别名叫做非堆,分析一下java虚拟机规范,之所以把方法区描述为堆的一个逻辑部分,应该觉得他们都是存储数据的角度出发的。一个存储对象数据(堆),一个存储静态信息(方法区)。
堆:
这块区域随着虚拟机的启动而创建。在实际的应用中,我们创建的对象和数组就是存放在堆里面。是一块线程不安全的,因为堆是一块共享的区域。程序员所熟悉的新生代,老年代,永久代的概念就是在堆里面,现在大多数的GC基本都采用了分代手机算法
新生代和老年代实际是根据对象存活的年龄来划分的。我们产生的新对象都是放在新生代(Eden Space)里面的,from放年龄比较大的,之后会被放到老年代 里面。过了一段时间gc(垃圾回收期)gc回收15次会将此对象放到老年代。
To Space:用于腾挪用的
标记-清除算法(Mark-Sweep)
1.标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象
2.在标记完成后统一回收所有被标记的对象
缺点:一个是效率问题,标记和清除两个过程的效率都不高
另一个是空间问题,标记清除后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后再程序运行过程中需要分配较大对象时,无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作。
标记-整理算法(Mark-Compact)
1.标记
2.让所有存活的对象都像一端移动,然后直接清理掉端边界以外的内存
复制算法(Copying)
1.将可用内存容量划分为大小相等的两块,每次只使用其中的一块。
2.当这一块内存用完了,就将还存活着的对象赋值到另一块上面,然后再把已使用过的内存空间一次清理到。
分代收集算法(Generational Collection)
1.根据对象存活周期的不同将内存划为几块。
2.一般是把java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。
3.在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用复制算法,只需要付出少量的复制成本就可以完成收集。
4.老年代中因为对象存活率高,没有额外空间对它进行分配担当,就必须使用“标记-清理”或者“标记-整理”算法来进行回收。
GC:垃圾回收器
1.是一个单线程的收集器,“Stop The World”
2.对于运行在Client模式下的虚拟机来说是一个很好的选择
3.简单而高效
Serial Old 收集器
1.Serial收集器的老年代版本,它同样是一个单线程收集器,使用“标记-整理”算法。
2.主要意义也是在于给Client模式下的虚拟机使用。
3.如果在Server模式下,那么它主要还有两大用途:
一种用途是在JDK1.5以及之前的版本中与Parallel Scavenge收集器搭配使用
另一种用途就是作为CMS收集器的后备预案,在并发收集发生Concurrent Mode Failue时使用。
CMS收集器---一款优秀的收集器
服务端默认就是CMS收集器
1.以获取最短回收停顿时间为目标的收集器
2.非常符合互联网站或者B/S系统的服务器端上,重视服务的响应速度,希望系统停顿时间最短的应用
3.基于“标记-清除”算法实现的。
4.CMS收集器的内存回收过程是与用户线程一起并发执行的
5.它的运作过程分为4个步骤,包括:
初始标记,“Stop The World”,只是标记一下GC Roots能直接关联到的对象,速度很快
并发标记,并发标记阶段就是进行GC RootTracing的过程。
重新标记,“Stop The World”,是为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,但远比并发标记的时间短
并发清除(CMS concurrent sweep)
6.优点:并发收集,低停顿
7.缺点:对CPU资源非常敏感
无法处理浮动垃圾,可能出现“Concurrent model Failure”失败而导致另一次Full GC的产生
一款基于“标记-清除”算法实现的收集器。
G1(Garbage-First)收集器
1.当今收集器技术发展的最前沿成果之一
2.G1是一款面向服务端应用的垃圾收集器
3.优点:
并行与并发:充分利用多cpu,多核环境下的硬件优势
分代收集:不需要其它收集器配合就能独立管理整个GC堆
空间整合:“标记-整理”算法实现的收集器,局部上基于“复制”算法不会产生内存空间碎片
可预测的停顿:能让使用者明确指定在一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒
4,G1
2.异常:
OutOfMemoryError:一般指堆空间溢出,主要是对象生成太多,而没有释放和销毁。
代码:
public class JvmException {
public static void main(String[] args) {
ArrayList<User> list = new ArrayList<User>();
while (true) {
list.add(new User());
}
}
}
报错:
StackOverFlowError:栈空间溢出,主要是方法调用层级太多,超过虚拟机所允许的最大层级。例如递归,没有结束条件会出现溢出。
本地方法栈:不是java虚拟机定义的,是java虚拟机外部定义的
在java虚拟机是一个箱子,程序在java虚拟机内部执行,java虚拟机有局限性,直接对内存的访问,java是访问不了的,这个时候需要写一些c或者c++写的代码,它可以绕过java虚拟机运行。那么我们如何用java程序调用这些代码呢?
所以
让外部的java语言的代码可以访问java虚拟机里使用其他语言编写的代码,所以java虚拟机提供了对外的接口。