JVM内存详解

1 本机内存介绍

1.1 硬件限制

1.2 操作系统和虚拟内存

1.2.1 虚拟内存可增加可用内存空间, 但是可能引起性能问题

1.2.2 内核空间和用户空间

2 内存耗尽时现象

当Java 堆耗尽时,Java 应用程序很难正常运行,因为Java 应用程序必须通过分配对象来完成工作。只要Java 堆被填满,就会出现糟糕的GC 性能并抛出表示Java 堆被填满的OutOfMemoryError。

相反,一旦Java运行时开始运行并且应用程序处于稳定状态,它可以在本机堆完全耗尽之后继续正常运行。不一定会发生奇怪的行为,因为需要分配本机内存的操作比需要分配Java 堆的操作少得多。但一些常见操作还是会报错:启动线程、加载类以及执行某种类型的网络和文件I/O。

3 如何占用本机内存

3.1 java堆

Java 堆是分配了对象的内存区域。

堆的大小可以在Java 命令行使用 -Xmx 和 -Xms 选项来控制(mx 表示堆的最大大小,ms 表示初始大小)。

Java堆占用的本机内存为-Xmx,未被使用的部分为保留内存,保留内存不会分配给其他程序使用;

对于维护Java 堆的内存管理系统,需要更多本机内存来维护它的状态。例如行垃圾收集。

3.2 垃圾收集

3.3 即时(JIT)编译

JIT 编译器在运行时编译Java 字节码来优化本机可执行代码。这极大地提高了Java 运行时的速度,并且支持Java 应用程序以与本机代码相当的速度运行。

但JIT 编译器的输入(字节码)和输出(可执行代码)必须也存储在本机内存中。

3.4 类和类加载器

存储类的方式取决于具体实现。Sun JDK 使用永久生成(permanent generation,PermGen)堆区域。Java 5 的IBM 实现会为每个类加载器分配本机内存块,并将类数据存储在其中。

从最基本的层面来看,使用更多的类将需要使用更多内存。

Java运行时可以卸载类来回收空间,但是只有在非常严酷的条件下才会这样做。不能卸载单个类,而是卸载类加载器,随其加载的所有类都会被卸载。只有在以下情况下才能卸载类加载器:

Java 堆不包含对表示该类加载器的 java.lang.ClassLoader 对象的引用。

Java 堆不包含对表示类加载器加载的类的任何 java.lang.Class 对象的引用。

在Java 堆上,该类加载器加载的任何类的所有对象都不再存活(被引用)。

需要注意的是,Java 运行时为所有Java 应用程序创建的3 个默认类加载器(bootstrap、extension 和 application )都不可能满足这些条件,因此,任何系统类(比如 java.lang.String)或通过应用程序类加载器加载的任何应用程序类都不能在运行时释放。

3.5 JNI

JNI 应用程序可能通过3 种方式增加Java 运行时的本机内存占用:

JNI 应用程序的本机代码被编译到共享库中,或编译为加载到进程地址空间中的可执行文件。大型本机应用程序可能仅仅加载就会占用大量进程地址空间。

本机代码必须与Java 运行时共享地址空间。任何本机代码分配或本机代码执行的内存映射都会耗用Java 运行时的内存。

某些JNI 函数可能在它们的常规操作中使用本机内存。GetTypeArrayElements 和GetTypeArrayRegion 函数可以将Java堆数据复制到本机内存缓冲区中,以供本机代码使用。是否复制数据依赖于运行时实现。(IBM Developer Kit for Java 5.0 和更高版本会进行本机复制)。

通过这种方式访问大量Java 堆数据可能会使用大量本机堆

3.6 NIO

直接bytebuffer会操作本机内存;

3.7 线程

线程的堆栈空间、线程本地存储(thread-local storage)和内部数据结构会占用本机内存。

堆栈大小因Java 实现和架构的不同而不同。一些实现支持为Java 线程指定堆栈大小,其范围通常在256KB 到756KB 之间。

4 调试方法和技术

4.1 检查java堆

JavaCore文件、heapdump文件;

4.2 检查本机堆

Windows 提供的PerfMon 工具;

Linux 使用命令行工具(比如 ps、top 和 pmap)能够显示应用程序的本机内存占用情况。配合使用GCMV,进行长时间跟踪后的分析。

由于JVM 前期阶段的本机内存增长而耗尽本机内存,以及内存使用随负载增加而增加,这些都是尝试在可用空间中做太多事情的例子。在这些场景中,您的选择是:

减少本机内存使用。缩小Java 堆大小是一个好的开端。

限制本机内存使用。如果您的本机内存随负载增加而增加,可以采取某种方式限制负载或为负载分配的资源。

增加可用地址空间。这可以通过以下方式实现:调优您的操作系统(例如,在Windows 上使用/3GB 开关增加用户空间,或者在Linux 上使用庞大的内核空间),更换平台(Linux 通常拥有比Windows 更多的用户空间),或者 转移到64 位操作系统。

4.3 是什么在使用本机内存

根据您的Java 设置,将会使用多少本机内存。根据以下指南粗略估算一下:

Java 堆占用的内存至少为-Xmx 值。

每个Java 线程需要堆栈空间。堆栈空间因实现不同而异,但是如果使用默认设置,每个线程至多会占用756KB 本机内存。

直接 ByteBuffer 至少会占用提供给allocate() 例程的内存值。

UMDH 支持就地 调试Windows 上本机内存泄漏,在Linux 上,您可能需要进行一些传统的调试,而不是依赖工具来解决问题。下面是一些建议的调试步骤:

提取测试案例。生成一个独立环境,您需要能够在该环境中再现本机内存泄漏。这将使调试更加简单。

尽可能缩小测试案例。尝试禁用函数来确定是哪些代码路径导致了本机内存泄漏。如果您拥有自己的JNI 库,可以尝试一次禁用一个来确定是哪个库导致了内存泄漏。

缩小Java 堆大小。Java 堆可能是进程的虚拟地址空间的最大使用者。通过减小Java 堆,可以将更多空间提供给本机内存的其他使用者。

关联本机进程大小。一旦您获得了本机内存随时间的使用情况,可以将其与应用程序工作负载和GC 数据比较。如果泄漏程度与负载级别成正比,则意味着泄漏是由每个事务或操作路径上的某个实体引起的。如果当进行垃圾收集时,本机进程大小显著减小,这意味着您没遇到内存泄漏,您拥有的是具有本机支持的对象组合(比如直接 ByteBuffer)。通过缩小Java 堆大小(从而迫使垃圾收集更频繁地发生),或者在一个对象缓存中管理对象(而不是依赖于垃圾收集器来清理对象),您可以减少本机支持对象持有的内存量。

5 消除限制

更改为64位,但是64位可能引入对象膨胀的问题;

必须关注物理内存是否满足Java程序使用,一旦物理内存不足,发生频繁的与虚拟内存交换,会严重影响性能。

JVM内存详解-阅读笔记的更多相关文章

  1. Java中堆内存和栈内存详解2

    Java中堆内存和栈内存详解   Java把内存分成两种,一种叫做栈内存,一种叫做堆内存 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配.当在一段代码块中定义一个变量时,ja ...

  2. NGINX高性能Web服务器详解(读书笔记)

    原文地址:NGINX高性能Web服务器详解(读书笔记) 作者:夏寥寥 第4章  Nginx服务器的高级配置 4.1 针对IPv4的内核7个参数的配置优化 说明:我们可以将这些内核参数的值追加到Linu ...

  3. 孙鑫视频VC++深入详解学习笔记

    孙鑫视频VC++深入详解学习笔记 VC++深入详解学习笔记 Lesson1: Windows程序运行原理及程序编写流程 Lesson2: 掌握C++基本语法 Lesson3: MFC框架程序剖析 Le ...

  4. DDR3内存详解,存储器结构+时序+初始化过程

    DDR3内存详解,存储器结构+时序+初始化过程 标签: DDR3存储器博客 2017-06-17 16:10 1943人阅读 评论(1) 收藏 举报  分类: 硬件开发基础(2)  转自:http:/ ...

  5. NAND_FLASH_内存详解与读写寻址方式

    一.内存详解 NAND闪存阵列分为一系列128kB的区块(block),这些区块是 NAND器件中最小的可擦除实体.擦除一个区块就是把所有的位(bit)设置为"1"(而所有字节(b ...

  6. JVM结构详解

    JVM 结构详解 JVM 结构图 程序计数器(PC 寄存器) 程序计数器的定义 程序计数器是一块较小的内存空间,是当前线程正在执行的那条字节码指令的地址.若当前线程正在执行的是一个本地方法,那么此时程 ...

  7. TCP/IP详解学习笔记

    TCP/IP详解学习笔记(1)-基本概念 TCP/IP详解学习笔记(2)-数据链路层 TCP/IP详解学习笔记(3)-IP协议,ARP协议,RARP协议 TCP/IP详解学习笔记(4)-ICMP协议, ...

  8. [转]JVM指令详解(上)

    作者:禅楼望月(http://www.cnblogs.com/yaoyinglong) 本文主要记录一些JVM指令,便于记忆与查阅. 一.未归类系列A 此系列暂未归类. 指令码    助记符      ...

  9. TCP/IP详解学习笔记 这位仁兄写得太好了

      TCP/IP详解学习笔记(1)-基本概念 为什么会有TCP/IP协议 在世界上各地,各种各样的电脑运行着各自不同的操作系统为大家服务,这些电脑在表达同一种信息的时候所使用的方法是千差万别.就好像圣 ...

随机推荐

  1. [GitHub]第八讲:GitHub Pages

    Github Pages 是 github 公司提供的免费的静态网站托管服务,用起来方便而且功能强大,不仅没有空间限制,还可以绑定自己的域名.在 https://pages.github.com/ 首 ...

  2. uploadify 3.2 java应用丢失session

    flash中有个bug就是自身创建一个session,这样就导致与web本身的session不一致 权限验证失败的问题.  原因: 因为uploadify是不会自动传送session值的,所以当ses ...

  3. SQL Server性能优化与管理的艺术 附件下载地址

    首先感谢读者们对鄙人的支持,购买了<SQL Server性能优化与管理的艺术>,由于之前出版社的一些疏忽,附件没有上传成功,再次本人深表歉意. 请需要下载附件的读者从下面链接下载,谢谢: ...

  4. Java Web 高性能开发,第 2 部分: 前端的高性能

    Web 发展的速度让许多人叹为观止,层出不穷的组件.技术,只需要合理的组合.恰当的设置,就可以让 Web 程序性能不断飞跃.Web 的思想是通用的,它们也可以运用到 Java Web.这一系列的文章, ...

  5. ROS(indigo)_turtlebot仿真示例包括stage和gazebo

    ROS(indigo)_turtlebot仿真示例包括stage和gazebo 现上参考网址: turtlebot:http://wiki.ros.org/Robots/TurtleBot stage ...

  6. 2015&nbsp;Objective-C&nbsp;三大新特性

    Overview 自 WWDC 2015 推出和开源 Swift 2.0 后,大家对 Swift 的热情又一次高涨起来,在羡慕创业公司的朋友们大谈 Swift 新特性的同时,也有很多像我一样工作上依然 ...

  7. 【Android】自定义ListView的Adapter报空指针异常解决方法

    刚刚使用ViewHolder的方法拉取ListView的数据,但是总会报异常.仔细查看代码,都正确. 后来打开adapter类,发现getView的返回值为null. 即return null. 将n ...

  8. 小强的HTML5移动开发之路(3)——HTML5与HTML4比较

    来自:http://blog.csdn.net/dawanganban/article/details/17652873 在前面介绍了HTML5的新特性,新标签的使用,智能表单设计,引入多媒体对象,C ...

  9. Ionic APP-Web SPA开发进阶(一)AngularJS全栈工程狮进阶

    AngularJS全栈工程狮进阶 前言 学习了一段时间AngularJS,开始接触移动端APP开发.为了响应公司开发需求,采用"Hybrid"混血开发方法.采用Ionic前端框架, ...

  10. 14_Android中Service的使用,关于广播接收者的说明

     服务:长期后台运行的没有界面的组件 android应用:什么地方需要用到服务? 天气预报:后台的连接服务器的逻辑,每隔一段时间获取最新的天气信息 股票显示:后台的连接服务器的逻辑,每隔一段时间获 ...