JVM的内存和GC
内存
栈内存(虚拟机栈和本地方法栈)
每个线程存有一个虚拟机栈,方法调用会生成一个栈帧,压入虚拟机栈。
StackOverFlowError异常
若单个线程请求的栈深度大于虚拟机允许的深度,则会抛出StackOverflowError(栈溢出错误)。可以通过无限递归来模拟,优化方式可以增大栈内存大小,以此来增加每个栈可以容纳的栈帧数量。
栈区内存溢出
不同于StackOverflowError,OutOfMemoryError指的是当整个虚拟机栈内存耗尽,并且无法再申请到新的内存时抛出的异常。可以通过不断新建线程模拟,优化方式,可以通过减小每个栈的大小,来增加线程数量。
方法区
存放静态变量,常量池和类的信息。使用cglib、bytecode等手段动态生成的类要更多关注方法区部分的内存。
堆内存
存放对象(类实例)信息
GC
GC算法
标记清除
标记-清除
- 优点:算法简单,效率较好
- 缺点:清除后,内存比较分散,不利于使用
复制
将堆内存分为两块,在GC时将一块存活的对象复制到另一块,清除第一块
- 优点:清除后,内存更规则
- 缺点:只能使用1/2的内存空间,代价较高
复制演进(根据IBM的调查,表示98%的对象都是朝生夕死的)
将内存分为一块Eden(较大80%)和两块Survivor(较小10%,from和to)。在清理时,将from和eden中存活的对象,复制到to,清除from和eden,新建的对象在eden上。