一、Java内存的构成
先上一个官方java document里的图:
由上图可知,整块区域分为Young Generation、Tenured Generation、Permanent Generation。
详细解释一下Young区:
Young区又分为:Eden、Survivor Space。
Survivor Space又分为 To Survivor、 From Survivor,如下图所示:
Java内存分为 堆内存(heap)和 Permanent区。
1、Java堆内存(heap):
--是 JVM 用于分配 Java 对象的内存,包含活动对象和不可用对象
--堆大小通常是在服务器启动时使用 java 命令中的 –Xms(最小) –Xmx(最大)标志来定义。
2、Permanent区:
--指内存的永久保存区域
--是Sun JDK和HP JDK用来加载类(class)和Meta信息的专门的内存区
--这个区域不归属Java堆内存(heap)范围
--Class在被Loader时就会被放到此,如果Java应用很大,例如类(class)很多,那么建议增大这个区域的大小来满足加载这些类的内存需求
--通过–XX:PermSize=***M –XX:MaxPermSize=***M调整
这里还有一个本地内存的概念:
·本地内存(native memory):
--是 JVM 用于其内部操作的本地内存(非Java内存)
--JNI 代码和第三方本地模块(例如,本地 JDBC 驱动程序)也使用本地内存
--最大本地内存大小取决于以下因素:操作系统进程内存大小限制、已经指定用于 Java 堆的内存
也就是说,整个物理机的内存可以说由以下部分构成:
物理内存 = Java 内存 + 本地内存 + 操作系统保留的内存
二、垃圾回收(Garbage Collection,GC)
1、为什么要垃圾回收
--JVM自动检测和释放不再使用的内存。
--Java 运行时JVM会执行 GC,这样程序员不再需要显式释放对象。
2、垃圾回收(GC)的分类
--Minor GC
--Full GC
3、垃圾回收(GC)的产生过程
1)新生成的对象在Eden区完成内存分配
2)当Eden区满了,再创建对象,会因为申请不到空间,触发minorGC,进行young(eden+1survivor)区的垃圾回收。(为什么是eden+1survivor:两个survivor中始终有一个survivor是空的,空的那个被标记成To Survivor)
3)minorGC时,Eden不能被回收的对象被放入到空的survivor(也就是放到To Survivor,同时Eden肯定会被清空),另一个survivor(From Survivor)里不能被GC回收的对象也会被放入这个survivor(To Survivor),始终保证一个survivor是空的。(MinorGC完成之后,To Survivor 和 From Survivor的标记互换)
4)当做第3步的时候,如果发现存放对象的那个survivor满了,则这些对象被copy到old区,或者survivor区没有满,但是有些对象已经足够Old(通过XX:MaxTenuringThreshold参数来设置),也被放入Old区
5)当Old区被放满的之后,进行完整的垃圾回收,即 Full GC
6)Full GC时,整理的是Old Generation里的对象,把存活的对象放入到Permanent Generation里。
4、垃圾回收的回收器
--串行(–XX:+UseSerialGC )
Out of Box算法,年轻代串行复制,年老代串行标记整理,主要用于桌面应用
--并行(–XX:+UseParallelGC )
年轻代暂停应用程序,多个垃圾收集线程并行的复制收集,年老代暂停应用程序,与串行收集器一样,单垃圾收集线程标记整理。JDK 6.0启用该算法后,默认启用了-XX:+UseParallelOldGC,性能大为提高
--并发(Concurrent Low Pause Collector)( –XX:+UseConcMarkSweepGC )
启用该参数,默认启用了-XX:+UseParNewGC;简单的说,并发是指用户线程与垃圾收集线程并发,程序在继续运行,而垃圾收集程序运行于其他CPU上。
三、Java内存的调优参数
-Xmx1024m:
设置JVM最大可用内存为1024M。
-Xms1024m:
设置JVM促使内存为1024M。此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存。
-Xmn512m:
设置年轻代大小为512M。(持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。)
-Xss128k:
设置每个线程的堆栈大小。这个值可以根据应用的线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成。
-XX:NewRatio=4
设置年轻代(包括Eden和两个Survivor区)与年老代的比值(总的大小是Xms的值)。设置为4,则年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5。
举个例子,-Xms 设置为 1024m,-Xmx 也设置为 1024m的情况下:
·年轻代 = 1024M/5 = 204.8M
·年老代 = 1024M/5*4 = 819.2M
如果-Xms和-Xmx的值设置的不一样,可以添加 -XX:MinHeapFreeRatio=<minimum> 和 -XX:MaxHeapFreeRatio=<maximum> 参数,使内存的大小能够在 大于 -Xms 和 小于 -Xmx 之间的范围内自动调整,所以内存中会有Virtual的空间(我是这样理解的,不是太清楚,这里需要大家指教)
By default, the virtual machine grows or shrinks the heap at each collection to try to keep the proportion of free space to live objects at each collection within a specific range. This target range is set as a percentage by the parameters -XX:MinHeapFreeRatio=<minimum> and -XX:MaxHeapFreeRatio=<maximum>, and the total size is bounded below by -Xms and above by -Xmx .
-XX:SurvivorRatio=4:
设置年轻代中Eden区与Survivor区的大小比值。设置为4,则两个Survivor区与一个Eden区的比值为2:4,一个Survivor区占整个年轻代的1/6
-XX:MaxPermSize=16m:
设置持久代大小为16m。
-XX:MaxTenuringThreshold=0:
设置垃圾最大年龄。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。对于年老代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,增加在年轻代即被回收的概论。
四、内存分配中会出现的错误
关于内存最常见的错误应该是这两个:
-- 内存溢出 Out Of Memory(OOM)
-- 内存泄露 Memory Leak (ML)
1、内存溢出
内存溢出发生在这种状况下:Java内存完成Minor GC 之后想要把还存活的对象放到 Old区 里,但是这时Old区 已经满了,同时 Permanent区也已经放不下存活的对象。这时就会产生 OOM 错误。
2、内存泄露
在Java中,内存泄漏就是存在一些被分配的对象,这些对象有下面两个特点,首先,这些对象是有被引用的,即在有向树形图中,存在树枝通路可以与其相连;其次,这些对象是无用的,即程序以后不会再使用这些对象。如果对象满足这两个条件,这些对象就可以判定为Java中的内存泄漏,这些对象不会被GC所回收,然而它却占用内存。
找到一个例子:
“这里引用一个常看到的例子,在下面的代码中,循环申请Object对象,并将所申请的对象放入一个Vector中,如果仅仅释放对象本身,但因为Vector仍然引用该对象,所以这个对象对GC来说是不可回收的。因此,如果对象加入到Vector后,还必须从Vector中删除,最简单的方法就是将Vector对象设置为null。
- Vector v = new Vector(10);
-
for (int i = 1; i < 100; i++)
- {
-
Object o = new Object();
- v.add(o);
-
o = null;
-
}//此时,所有的Object对象都没有被释放,因为变量v引用这些对象。
实际上这些对象已经是无用的,但还被引用,GC就无能为力了(事实上GC认为它还有用),这一点是导致内存泄漏最重要的原因。”
3、补充一个:PermGen space Error
因为 GC 不会在主程序运行期对PermGen space进行清理,所以如果应用中有很CLASS需要Load的话,就很可能出现PermGen space错误。
另外如果WEB APP下使用了大量的第三方jar, 其大小超过了 jvm 默认的大小那么也会产生此错误信息了。
五、总结
上面4点的内容可以跟下面这个图来进行融合:
======================= 全文完 =================
有错误的地方请大家指出。
- 大小: 21.5 KB
- 大小: 22.6 KB
- 大小: 20.6 KB
- 大小: 31.3 KB
分享到:
相关推荐
Java的自动垃圾回收机制也是一个显著优点,它减轻了程序员管理内存的负担,降低了程序出现内存泄漏的风险。此外,自JDK 1.5以来,Java的性能不断提升,使得Java在处理大量数据和高并发场景时表现优秀,甚至有人提出...
通过对内存管理机制的理解及上述几种常见内存泄露场景的认识,开发者可以更好地预防和解决这类问题。为了进一步提高代码的质量,建议在开发过程中结合单元测试和性能测试工具定期检查并修复潜在的内存泄露问题。
"谈谈对Java的认识" Java是一种高级编程语言,它的出现改变了整个软件开发的战略, 从单机时代向着以网络为中心的计算机时代转移。Java语言的特点包括简单、高级、面向对象、分布式、解释型、健壮、安全、体系结构...
Java内存管理问题是Java开发者在软件运行过程中经常会遇到的挑战之一,尤其在大型分布式系统中,内存泄漏、内存溢出...通过本分享的案例学习,可以加深对Java内存管理的认识,并能在实际遇到内存问题时快速定位和解决。
### 提高Java开发质量之内存泄露 #### 一、引言 ...对于Java开发者而言,在日常开发工作中加强对内存管理的认识和实践是非常必要的。通过持续改进开发流程和技术手段,可以显著提升软件的质量和稳定性。
因此,对`Object`类的理解是每个Java开发者的基本功。本文将深入探讨`Object`类,以及其核心方法`equals()`与Java中的`==`操作符之间的差异。 `Object`类位于Java的核心库`java.lang`包中,它提供了基本的方法来...
Java JVM 虚拟机选项 Xms Xmx PermSize MaxPermSize 是 Java 虚拟机(JVM)中用于配置内存管理的参数。这些参数控制着 JVM 中的堆内存和非堆内存的分配。 Xms:指定 JVM 初始分配的堆内存。默认值是物理内存的 1/64...
此外,Java还拥有严格的异常处理机制和沙箱模型,确保应用程序不会对系统的其他部分造成损害。 **4. 自动垃圾回收** 与C/C++不同,Java自动管理内存。这意味着程序员不需要手动分配和释放内存空间,减少了内存泄漏...
为了更好地理解Java虚拟机的内部工作原理,开发者通常需要对JVM规范有深入的认识。例如,对JVM的垃圾回收算法的了解,有助于开发者编写出更适合自动内存管理的代码。了解JVM的线程模型,有助于编写高性能的多线程...
Java的健壮性体现在自动内存管理,避免了内存泄漏等问题,同时限制了一些可能导致程序崩溃的语言特性,如全局变量和指针。 与C和C++相比,Java简化了许多概念,如没有全局变量、预处理指令(如#include和#define)...
Java是一种广泛使用的高级编程语言,由Sun Microsystems(后被甲骨文公司收购)于1995年发布。它的设计目标是实现“一次编写...观看这样的视频教程是学习Java的优秀起点,能快速建立起对Java语言的整体认识和实践能力。
在理解Java内存管理时,需要清楚地认识到Java的内存分配和释放与C/C++的不同,Java通过垃圾回收机制来管理内存,简化了开发者的内存管理任务,但同时也带来了一定的性能开销。而C/C++中开发者需要手动管理内存,如果...
以下是对"Java编程语言程序的认识误区"的详细解析。 1. **Java是完全跨平台的** 许多人认为Java“一次编写,到处运行”的口号意味着它在所有操作系统上都能无差异运行。实际上,虽然JVM(Java虚拟机)提供了跨平台...
第1章主要介绍了并行计算中相关的 些基本概念, 树立读者对并行计算的基本认识;介绍了两个重要的并行性能评估定律, 以及 Java 内存模型 JMM。第2章介绍了 Java 并行程序开发的基础, 包括 Java 中 Thread 的基本...
#### 1-2 认识Java语言 **1.2.1 Java语言的特性** Java是一种功能强大且用途广泛的编程语言,其核心特性包括: 1. **简单高效**:Java语言的设计理念之一就是简单易学,同时又具备高效的执行能力。它去除了许多...
在处理图形或者媒体文件时,尤其是像幻灯片这样需要展示多个图片的场景,`MediaTracker`能确保图片完全加载到内存中再进行显示,避免了因图片未完全加载而引起的闪烁或延迟问题。通过调用`addImage()`方法添加图片,...
通过深入学习“Java 第1章 了解java含源代码”,你将建立起对Java编程的初步认识,并为后续章节的学习打下坚实的基础。记住,实践是检验真理的唯一标准,动手编写和运行代码是学习编程的关键。祝你在Java的世界里...
二、Java内存管理 1. 内存区域:介绍堆、栈、方法区、本地方法栈等内存区域的工作原理和作用。 2. 垃圾回收:讲解垃圾收集的基本概念,包括可达性分析、引用类型、垃圾回收算法(如标记-清除、复制、标记-整理、分代...