关闭

JVM (Java虚拟机) 内存管理

标签: javajvmjdk内存管理
105人阅读 评论(0) 收藏 举报
分类:

Java不需要开发人员显式分配内存和回收内存,而是通过JVM来自动管理内存的分配和回收 ( 即GC )。这篇博文将用通俗易懂的方式来总结 JVM。

JVM的规范定义如下:
这里写图片描述

接下来我们分开来分析整个JVM。
1.JVM的内存管理:

这里写图片描述

如上图所示,Sun JDK 遵照JVM的规范,将内存划分为五部分,分别为:pc寄存器、JVM方法栈、本地方法栈、JVM方法区、JVM堆。

pc寄存器和JVM方法栈:

每个线程均会创建pc寄存器和JVM方法栈
pc寄存器占用的可能为cpu寄存器或者操作系统内存
JVM方法栈占用的是操作系统内存,JVM方法栈是线程私有
当方法运行完,其占用这两部分内存会自动释放。

本地方法栈:

本地方法栈用于支持本地方法的执行
存储了每个本地方法调用的状态
在Sun JDK 中,本地方法栈和JVM方法栈是同一个

JVM方法区:

存放了要加载的类的信息、类中的静态变量、类中定义的final类型的常量、类中的方法信息等。
方法区域是全局共享的
在Sun JDK 中方法区又称为持久代,默认最小值为16M,最大值为64M.
在一定条件下可以被GC.

JVM堆:
堆主要用于存储对象实例和数组值,Java中所有通过new创建的对象的内存都在堆中分配。由GC进行回收。
补充:老年代主要用来存放新生代中经过多次垃圾回收仍然存活的对象,例如缓存对象,新建的对象也有可能在老年代上分配内存(大对象或大的数组对象,且数组要保证无引用外部对象)。

关于堆的细节内容,请看我之前写的一篇博文:

Java GC、新生代、老年代

关于内存的分配问题:
Java对象所占有的内存主要是从堆上进行分配,堆是线程共享的,因此在堆上分配内存时需要加锁。当堆上空间不足时,会触发GC,若GC后空间仍然不足,则会抛出异常。

接下来,我们重点分析内存的回收:

JVM通过GC来回收堆和方法区中的内存
GC的基本原理是:
(1)先找到程序中不再被使用的对象
(2)回收这些对象所占用的内存
通常采用收集器的方式实现GC,主要的收集器有引用计数收集器和跟踪收集器。

1.引用计数收集器(分散式管理 ):
给每个对象设置一个引用计数器,当该对象被引用的时候,计数器的值加一,当计数器的值为0的时候,表示该对象没有被引用,即可以进行回收。
缺点:
(1)引用计数器需要在每次对象赋值时进行计数器的增减,有一定的消耗。
(2)引用计数器对于循环引用的场景没有办法进行回收。
所以,Java不使用这种收集器。
2.跟踪收集器 (集中式管理):

这里写图片描述

跟踪式收集器基于一定的条件触发,执行时需要从根集合扫描对象的引用关系,这会造成程序的暂停。

三种跟踪收集算法的缺点:
复制:成本是要增加一块新的内存以及进行对象的移动
标记--清除:会造成内存碎片
标记--压缩:不产生内存碎片但是对象移动成本高
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:17347次
    • 积分:447
    • 等级:
    • 排名:千里之外
    • 原创:30篇
    • 转载:0篇
    • 译文:0篇
    • 评论:1条
    最新评论