java内存管理详细介绍

c#小王子 c#小王子 2022-01-21 631 Java

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


概述:


对于从事 C、C++程序开发的开发人员来说,在内存管理领域,他们即是拥有最高权力的皇帝又是执行最基础工作的劳动人民——拥有每一个对象的“所有权”,又担负着每一个对象生命开始到终结的维护责任。


对于 Java 程序员来说,不需要在为每一个 new 操作去写配对的 delete/free,不容易出现内容泄漏和内存溢出错误,看起来由 JVM 管理内存一切都很美好。不过,也正是因为 Java 程序员把内存控制的权力交给了 JVM,一旦出现泄漏和溢出,如果不了解 JVM 是怎样使用内存的,那排查错误将会是一件非常困难的事情。


VM 运行时数据区域


JVM 执行 Java 程序的过程中,会使用到各种数据区域,这些区域有各自的用途、创建和销毁时间。根据《Java 虚拟机规范(第二版)》(下文称 VM Spec)的规定,JVM 包括下列几个运行时数据区域:


1.程序计数器(Program Counter Register):每一个 Java 线程都有一个程序计数器来用于保存程序执行到当前方法的哪一个指令,对于非Native 方法,这个区域记录的是正在执行的 VM 原语的地址,如果正在执行的是 Natvie 方法,这个区域则为空(undefined)。此内存区域是唯一一个在 VM Spec 中没有规定任何 OutOfMemoryError 情况的区域。


2.Java 虚拟机栈(Java Virtual Machine Stacks)与程序计数器一样,VM 栈的生命周期也是与线程相同。VM 栈描述的是 Java方法调用的内存模型:每个方法被执行的时候,都会同时创建一个帧(Frame)用于存储本地变量表、操作栈、动态链接、方法出入口等信息。每一个方法的调用至完成,就意味着一个帧在 VM 栈中的入栈至出栈的过程。在后文中,我们将着重讨论 VM 栈中本地变量表部分。


经常有人把 Java 内存简单的区分为堆内存(Heap)和栈内存(Stack),实际中的区域远比这种观点复杂,这样划分只是说明与变量定义密切相关的内存区域是这两块。其中所指的“堆”后面会专门描述,而所指的“栈”就是VM 栈中各个帧的本地变量表部分。本地变量表存放了编译期可知的各种标量类型(boolean、byte、char、short、int、float、long、double)、对象引用(不是对象本身,仅仅是一个引用指针)、方法返回地址等。其中 long和 double 会占用 2 个本地变量空间(32bit),其余占用 1 个。


本地变量表在进入方法时进行分配,当进入一个方法时,这个方法需要在帧中分配多大的本地变量是一件完全确定的事情,在方法运行期间不改变本地变量表的大小。


在 VM Spec 中对这个区域规定了 2 中异常状况:如果线程请求的栈深度大于虚拟机所允许的深度,将抛出 StackOverflowError 异常;如果 VM 栈可以动态扩展(VM Spec 中允许固定长度的 VM 栈),当扩展时无法申请到足够内存则抛出 OutOfMemoryError 异常。


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

本地方法栈与 VM 栈所发挥作用是类似的,只不过 VM 栈为虚拟机运行 VM 原语服务,而本地方法栈是为虚拟机使用到的 Native 方法服务。它的实现的语言、方式与结构并没有强制规定,甚至有的虚拟机(譬如 Sun Hotspot 虚拟机)直接就把本地方法栈和 VM 栈合二为一。和 VM 栈一样,这个区域也会抛出 StackOverflowError 和 OutOfMemoryError 异常。


4.Java 堆(Java Heap)

对于绝大多数应用来说,Java 堆是虚拟机管理最大的一块内存。Java 堆是被所有线程共享的,在虚拟机启动时创建。Java 堆的唯一目的就是存放对象实例,绝大部分的对象实例都在这里分配。这一点在 VM Spec 中的描述是:所有的实例以及数组都在堆上分配(原文:The heap is the runtime dataarea from which memory for all class instances and arrays isallocated),但是在逃逸分析和标量替换优化技术出现后,VM Spec 的描述就显得并不那么准确了。


Java 堆内还有更细致的划分:新生代、老年代,再细致一点的:eden、from survivor、to survivor,甚至更细粒度的本地线程分配缓冲(TLAB)等,无论对 Java 堆如何划分,目的都是为了更好的回收内存,或者更快的分配内存,在本章中我们仅仅针对内存区域的作用进行讨论,Java 堆中的上述各个区域的细节,可参见本文第二章《JVM 内存管理:深入垃圾收集器与内存

分配策略》。


根据 VM Spec 的要求,Java 堆可以处于物理上不连续的内存空间,它逻辑上是连续的即可,就像我们的磁盘空间一样。实现时可以选择实现成固定大小的,也可以是可扩展的,不过当前所有商业的虚拟机都是按照可扩展来实现的(通过-Xmx 和-Xms 控制)。如果在堆中无法分配内存,并且堆也无法再扩展时,将会抛出 OutOfMemoryError 异常。


5.方法区(Method Area)

叫“方法区”可能认识它的人还不太多,如果叫永久代(PermanentGeneration)它的粉丝也许就多了。它还有个别名叫做 Non-Heap(非堆),

但是 VM Spec 上则描述方法区为堆的一个逻辑部分(原文:the method areais logically part of the heap),这个名字的问题还真容易令人产生误

解,我们在这里就不纠结了。方法区中存放了每个 Class 的结构信息,包括常量池、字段描述、方法描述等等。VM Space 描述中对这个区域的限制非常宽松,除了和 Java 堆一样不需要连续的内存,也可以选择固定大小或者可扩展外,甚至可以选择不实现垃圾收集。相对来说,垃圾收集行为在这个区域是相对比较少发生的,但并不是某些描述那样永久代不会发生 GC(至少对当前主流的商业 JVM 实现来说是如此),这里的 GC 主要是对常量池的回收和对类的卸载,虽然回收的“成绩”一般也比较差强人意,尤其是类卸载,条件相当苛刻。


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

Class 文件中除了有类的版本、字段、方法、接口等描述等信息外,还有一项信息是常量表(constant_pool table),用于存放编译期已可知的常量,

这部分内容将在类加载后进入方法区(永久代)存放。但是 Java 语言并不要求常量一定只有编译期预置入 Class 的常量表的内容才能进入方法区常量池,运行期间也可将新内容放入常量池(最典型的 String.intern()方法)。运行时常量池是方法区的一部分,自然受到方法区内存的限制,当常量池无法在申请到内存时会抛出 OutOfMemoryError 异常。


7.本机直接内存(Direct Memory)

直接内存并不是虚拟机运行时数据区的一部分,它根本就是本机内存而不是VM 直接管理的区域。但是这部分内存也会导致 OutOfMemoryError 异常出现,因此我们放到这里一起描述。


在 JDK1.4 中新加入了 NIO 类,引入一种基于渠道与缓冲区的 I/O 方式,它可以通过本机 Native 函数库直接分配本机内存,然后通过一个存储在 Java堆里面的 DirectByteBuffer 对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在 Java 对和本机堆中来回复制数据。显然本机直接内存的分配不会受到 Java 堆大小的限制,但是即然是内存那肯定还是要受到本机物理内存(包括 SWAP 区或者 Windows 虚拟内存)的限制的,一般服务器管理员配置 JVM 参数时,会根据实际内存设置-Xmx 等参数信息,但经常忽略掉直接内存,使得各个内存区域总和大于物理内存限制(包括物理的和操作系统级的限制),而导致动态扩展时出现 OutOfMemoryError异常。


实战 OutOfMemoryError

上述区域中,除了程序计数器,其他在 VM Spec 中都描述了产生OutOfMemoryError(下称 OOM)的情形,那我们就实战模拟一下,通过几段简单的代码,令对应的区域产生 OOM 异常以便加深认识,同时初步介绍一些与内存相关的虚拟机参数。下文的代码都是基于 Sun Hotspot 虚拟机 1.6 版的实现,对于不同公司的不同版本的虚拟机,参数与程序运行结果可能结果会有所差别。


Java 堆

Java 堆存放的是对象实例,因此只要不断建立对象,并且保证 GC Roots 到对象之间有可达路径即可产生 OOM 异常。测试中限制 Java 堆大小为 20M,不可扩展,通过参数-XX:+HeapDumpOnOutOfMemoryError 让虚拟机在出现 OOM 异常的时候 Dump 出内存映像以便分析。(关于 Dump 映像文件分析方面的内容,可参见本文第三章《JVM 内存管理:深入 JVM 内存异常分析与调优》。)

清单 1:Java 堆 OOM 测试


/**
* VM Args:-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError
* @author zzm
*/
public class HeapOOM {
static class OOMObject {
}
public static void main(String[] args) {
List<OOMObject> list = new
ArrayList<OOMObject>();
while (true) {
list.add(new OOMObject());
} 
} 
}


运行结果


java.lang.OutOfMemoryError: Java heap space

Dumping heap to java_pid3404.hprof ...

Heap dump file created [22045981 bytes in 0.663 secs]


【下载地址】

百度网盘链接:https://pan.baidu.com/s/1se08tDEuqtDebTP-Y9hh5Q

提取码:7u43


相关文章


使用-JFreeChart来创建基于web的图表

使用-JFreeChart来创建基于web的图表

XStream使用文档

XStream使用文档

WebService发布过程及常见问题

WebService发布过程及常见问题

webpack实战入门进阶调优分享

webpack实战入门进阶调优分享

weblogic调优参数及监控指标

weblogic调优参数及监控指标

weblogic节点管理

weblogic节点管理

weblogic管理控制台概述

weblogic管理控制台概述

weblogic-部署和启动

weblogic-部署和启动

WebLogic-Server-性能及调优-调优-Java-虚拟机

Java 虚拟机(Java virtual machine,简称 JVM)是一种虚拟“执行引擎”实例,可在微处理器上执行 Java 类文件中的字节码。调整 JVM 的方式会影响 Weblogic Server 和应用程序的性能。

Velocity用户教程

Velocity是一个基于java的模板引擎(template engine)。它允许任何人仅仅简单的使用模板语言(template language)来引用由java代码定义的对象。

Velocity用户手册

Velocity 用户手册是帮助页面设计者和内容提供者认识 Velocity 和其简单而功能强大的脚本语言――Velocity 模板语言(VTL)。在手册上的许多例子,都是用 Velocity 插入动态的内容到网页上,但是所有的 VLT 例子都能应用到其他的页面和模板中。


文章热度: 166291
文章数量: 333
推荐阅读

FlashFXP绿色版网盘下载,附激活教程 1781

FlashFxp百度网盘下载链接:https://pan.baidu.com/s/1MBQ5gkZY1TCFY8A7fnZCfQ。FlashFxp是功能强大的FTP工具

Adobe Fireworks CS6 Ansifa绿色精简版网盘下载 1564

firework可以制作精美或是可以闪瞎眼的gif,这在广告领域是需要常用的,还有firework制作下logo,一些原创的图片还是很便捷的,而且fireworks用法简单,配合dw在做网站这一块往往会发挥出很强大的效果。百度网盘下载链接:https://pan.baidu.com/s/1fzIZszfy8VX6VzQBM_bdZQ

navicat for mysql中文绿色版网盘下载 1623

Navicat for Mysql是用于Mysql数据库管理的一款图形化管理软件,非常的便捷和好用,可以方便的增删改查数据库、数据表、字段、支持mysql命令,视图等等。百度网盘下载链接:https://pan.baidu.com/s/1T_tlgxzdQLtDr9TzptoWQw 提取码:y2yq

火车头采集器(旗舰版)绿色版网盘下载 1707

火车头采集器是站长常用的工具,相比于八爪鱼,简洁好用,易于配置。火车头能够轻松的抓取网页内容,并通过自带的工具对内容进行处理。站长圈想要做网站,火车头采集器是必不可少的。百度网盘链接:https://pan.baidu.com/s/1u8wUqS901HgOmucMBBOvEA

Photoshop(CS-2015-2023)绿色中文版软件下载 1823

安装文件清单(共46G)包含Window和Mac OS各个版本的安装包,从cs到cc,从绿色版到破解版,从安装文件激活工具,应有尽有,一次性打包。 Photoshop CC绿色精简版 Photoshop CS6 Mac版 Photoshop CC 2015 32位 Photoshop CC 2015 64位 Photoshop CC 2015 MAC版 Photoshop CC 2017 64位 Adobe Photoshop CC 2018 Adobe_Photoshop_CC_2018 Photoshop CC 2018 Win32 Photoshop CC 2018 Win64

知之

知之平台是全球领先的知识付费平台。提供各个领域的项目实战经验分享,提供优质的行业解决方案信息,来帮助您的工作和学习

使用指南 建议意见 用户协议 友情链接 隐私政策 Powered by NOOU ©2020 知之