JVM内存管理

JVM内存管理与调优

    Java 与 C++ 之间有一堵由内存动态分配和垃圾收集技术所围成的“高墙”,墙外面的人想进去,墙里面的人想出来。

——《深入理解Java虚拟机》周志明

注:本文系《深入理解Java虚拟机》的读书笔记,外带扩展总结,部分内容直接照搬于原文,如有叙述不尽,请阅读原书。 ———-

一、Java内存区域

这里写图片描述

在以前看的资料中,通常将虚拟机内存划分为堆内存和栈内存。如上图所示,真实的虚拟机内存划分远比这个复杂。我们通常说的栈内存即指虚拟机栈,堆内存就是上图中的“堆Heap”。下面一一介绍虚拟机各个内存区域的作用和特点


1. 程序计数器(Program Counter Register)

  1. 当前线程执行字节码的行号指示器;
  2. 线程独立,每个线程都有一个程序计数器;
  3. 线程执行Java方法,这个计数器存储字节码内存地址;
  4. 线程执行Native方法,这个计数器值为空(Undefined);
  5. 唯一一个没有OutOfMemoryError的区域

2. 虚拟机栈(VM Stack)

  1. 线程私有,生命周期与线程同步
  2. 每个方法被执行的时候都会同时创建一个栈帧(Stack Frame)
  3. 存储局部变量表、操作栈、动态链接、方法出口等信息
  4. 局部变量表存放了编译期可知的各种基本数据类型、对象引用、returnAddress类型(字节码地址)
  5. 异常:OutOfMemoryError和StackOverflowError

该区域(或局部变量表部分)即我们通常所说的“栈”内存,与“堆”内存对应。


3. 本地方法栈(Native Method Stack)

  1. 与虚拟机栈所发挥的作用是非常相似的
  2. 为执行本地方法服务
  3. 在JDK自带虚拟机HotSpot中,与VM Stack合并
  4. 异常:同虚拟机栈

4. 堆(Heap)

  1. 线程共享区域
  2. 唯一目的:存放对象实例,无论怎么划分区域
  3. 垃圾管理的主要区域,GC堆(Garbage Collected Heap)
  4. 分代回收:新生代、老年代
  5. 细致划分:Eden 空间、From Survivor 空间、To Survivor 空间
  6. 内存分配角度:线程共享的Java 堆中可能划分出多个线程私有的分配缓冲区(Thread Local Allocation Buffer,TLAB)
  7. 逻辑连续区域,不要求物理连续

注:内存的大小,会直接影响GC回收时间,Full GC又会停止所有用户进程,从而影响应用相应时间。在内存回收详细讲述。


5. 方法区(Method Area)

  1. 线程共享区域
  2. 存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据
  3. 堆的逻辑部分(虚拟机规范),但是它却有一个别名叫做Non-Heap(非堆),目的应该是与Java 堆区分开来
    • 在HotSpot中,也被成为永久代(Permanent Generation、简称Perm),本质上两者并不等价,仅仅是因为HotSpot 虚拟机的设计团队选择把GC 分代收集扩展至方法区,或者说使用永久代来实现方法区而已
  4. 虚拟机规范中,该区域可以不实现垃圾回收
  5. 回收是有必要的,在Sun 公司的BUG 列表中,曾出现过的若干个严重的BUG 就是由于低版本的HotSpot 虚拟机对此区域未完全回收而导致内存泄漏
  6. 异常:OutOfMemoryError

6. 运行时常量池(Runtime Constant Pool)

  1. 方法区的一部分
  2. Class 文件中除了有类的版本、字段、方法、接口等描述等信息外,还有一项信息是常量池,用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中
  3. 运行时常量池相对于Class 文件常量池的另外一个重要特征是具备动态性,Java 语言并不要求常量一定只能在编译期产生,也就是并非预置入Class 文件中常量池的内容才能进入方法区运行时常量池,运行期间也可能将新的常量放入池中,这种特性被开发人员利用得比较多的便是String 类的intern() 方法
  4. 除了保存Class 文件中描述的符号引用外,还会把翻译出来的直接引用也存储在运行时常量池中
  5. 异常:OutOfMemoryError

7. 直接内存(Direct Memory)

  1. 并不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域
  2. 在JDK 1.4 中新加入了NIO(New Input/Output)类,引入了一种基于通道(Channel)与缓冲区(Buffer)的I/O 方式,它可以使用Native 函数库直接分配堆外内存,然后通过一个存储在Java 堆里面的DirectByteBuffer 对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在Java 堆和Native 堆中来回复制数据
  3. 收到本机总内存和寻址空间的限制
  4. 异常:OutOfMemoryError


二、JVM内存回收机制

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值