`
Tonyguxu
  • 浏览: 277863 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

JVM内存管理

 
阅读更多

为了保证java内存不会溢出,java中有垃圾回收机制。垃圾回收机制是指jvm用于释放那些不再使用的对象所占用的内存。java语言并不要求jvm有gc,也没有规定gc如何工作。垃圾收集的目的在于清除不再使用的对象。gc通过确定对象是否被活动对象引用来确定是否收集该对象。

  内存溢出就是你要求分配的java虚拟机内存超出了系统能给你的,系统不能满足需求,于是产生溢出。

  内存泄漏是指你向系统申请分配内存进行使用(new),可是使用完了以后却不归还(delete),结果你申请到的那块内存你自己也不能再访问,该块已分配出来的内存也无法再使用,随着服务器内存的不断消耗,而无法使用的内存越来越多,系统也不能再次将它分配给需要的程序,产生泄露。一直下去,程序也逐渐无内存使用,就会溢出。(内存泄露vs内存溢出

【内存空间的划分】

Sun JDK实现时遵照JVM规范,将内存空间划分为方法区、堆、JVM方法栈、本地方法栈及pc寄存器。

* 方法区:

存放要加载的类or接口的信息(名称、修饰符等)、类的static变量、final常量、Field信息、方法信息(元数据)。通过Class对象获取的相关数据就来自该区域。 --见 Class类

Sun JDK中这块区域对应Permanet Generation(持久代),默认最小值为16MB,最大值为64MB,可通过-XX:PermSize-XX:MaxPermSize来设置最小值和最大值。

* 堆(Heap Memory)

存放对象实例及数组值,Heap中对象所占用的内存由GC进行回收,在32位系统上最大为2G,64位系统上无限制。可通过-Xms-Xmx控制,-Xms为JVM启动时申请的最小Heap内存,-Xmx为JVM可申请的最大Heap内存。

* 方法栈

每个线程均会创建PC寄存器和方法栈。方法栈中有栈帧。方法栈为线程私有。当方法运行完毕,该方法对应的栈帧所占用的空间自动释放。

--想到 ThreadLocal

方法栈空间不足时,抛出StackOverflowError错误(如不合理的递归调用),在Sun JDK中可通过-Xss设置大小。 

 

【Heap Memory详解】


{    [  (Eden)(S0)(S1)  ]     [ (          ) ]    }

    |----New Gen------|    |-Old Gen--|

|---------------heap-----------------------|

-New Generation:新生代

大多数情况下java程序中新建的对象都从新生代分配内存,新生代由Eden Space和两块相同大小的Survivor Space构成。可通过-Xmn指定新生代的大小。

  -Eden Space:创建对象,依据的是方法区中存放的类的元数据。

  -S0:当Eden Space空间用完时,JVM的垃圾回收器对其进行回收,将Eden中不被其他对象使用的对象进行销毁,同时将Eden中还被其他对象引用的对象移到S0区,如果S0区也没有空间了则移动到S1区。

  -S1

-Old Generation:旧生代

存放新生代中经过多次垃圾回收仍然存活的对象,例如缓存对象。旧生代占用大小为-Xmx值减-Xmn对应的值。


------Shallow Heap


java.lang.OutOfMemoryError: GC overhead limit exceeded

这个是JDK6新添的错误类型。是发生在GC占用大量时间而很少的堆被恢复的时候发生的,是一种保护机制。解决方案是,关闭该功能,使用 -XX:-UseGCOverheadLimit

Sun官方解释:

The parallel / concurrent collector will throw an OutOfMemoryError if too much time is being spent in garbage collection: if more than 98% of the total time is spent in garbage collection and less than 2% of the heap is recovered, an OutOfMemoryError will be thrown. This feature is designed to prevent applications from running for an extended period of time while making little or no progress because the heap is too small. If necessary, this feature can be disabled by adding the option -XX:-UseGCOverheadLimit to the command line

如何避免:查看是否有使用大内存的代码或死循环。



System.gc() 与 finalize()】

java.lang.System.gc()

java.lang.Runtime.getRuntime().gc()

java.lang.Object.finalize()

一个题目:
11. rbo = new ReallyBigObject();
12. // more code here
13. rbo = null;
14.
Which statement should be placed at line 14 to suggest that the virtual
machine expend effort toward recycling the memory used by the
object rbo?
A. System.gc();
B. Runtime.getRuntaime().gc();

C. System.freeMemory();
D. Runtime.getRuntime().growHeap();
E. Runtime.getRuntime().freeMemory();


gc()有何用?

  调用 gc 方法暗示着 Java 虚拟机做了一些努力来回收未用对象,以便能够快速地重用这些对象当前占用的内存。当控制权从方法调用中返回时,虚拟机已经尽最大努力从所有丢弃的对象中回收了空间。 
调用 System.gc() 等效于调用Runtime.getRuntime().gc()


finalize()有何用?

  gc 只能清除在堆上分配的内存(纯java语言的所有对象都在堆上使用new分配内存),而不能清除栈上分配的内存(当使用JNI技术时,可能会在栈上分配内存,例如java调用c程序,而该c程序使用malloc分配内存时)。因此,如果某些对象被分配了栈上的内存区域,那gc就管不着了,对栈上的对象进行内存回收就要靠finalize()。
举个例子来说,当java 调用非java方法时(这种方法可能是c或是c++的),在非java代码内部也许调用了c的malloc()函数来分配内存,而且除非调用那个了 free() 否则不会释放内存(因为free()是c的函数),这个时候要进行释放内存的工作,gc是不起作用的,因而需要在finalize()内部的一个固有方法调用free()。
finalize的工作原理应该是这样的:一旦垃圾收集器准备好释放对象占用的存储空间,它首先调用finalize(),而且只有在下一次垃圾收集过程中,才会真正回收对象的内存.所以如果使用finalize(),就可以在垃圾收集期间进行一些重要的清除或清扫工作.


finalize()在什么时候被调用?
有三种情况
1.所有对象被Garbage Collection时自动调用,比如运行System.gc()后.
2.程序退出时为每个对象调用一次finalize方法。
3.显式的调用finalize方法


除此以外,正常情况下,当某个对象被系统收集为无用信息的时候,finalize()将被自动调用。但是jvm不保证finalize()一定被调用,也就是说,finalize()的调用是不确定的,这也就是为什么sun不提倡使用finalize()的原因. 简单来讲,finalize()是在对象被GC回收前会调用的方法,而System.gc()建议而非强制GC开始回收工作,具体执行要看GC的执行策略。

调用了 System.gc() 之后,java 在内存回收过程中就会调用那些要被回收的对象的 finalize() 方法。


【待看】

1.Calling System.gc() is a bad idea

2.System.gc() in Java

3.System.GC 算法

分享到:
评论

相关推荐

    JVM 内存管理之道

    JVM 内存管理之道 JVM垃圾回收机制 JVM GC组合 JVM 内存监控工具

    JVM内存管理白皮书

    在这份由Sun Microsystems公司出版的《JVM内存管理白皮书》中,我们可以找到关于Java虚拟机(JVM)内存管理的详细介绍和深入分析。这份文档对于想要深入了解JVM工作原理的读者来说是一份宝贵的学习资料。在这份...

    jvm内存管理,pdf

    ### JVM内存管理详解 #### 一、引言 在探讨JVM内存管理之前,我们先来看一下为何要深入了解这一主题。对于深入掌握Java的人来说,内存管理是不可或缺的一部分。随着技术的发展,内存管理变得越来越自动化,但这也...

    JVM-内存管理 2012-12.pdf

    JVM内存管理是Java平台的一个重要特性,其内存空间的分配和回收机制对Java应用程序的性能和稳定性有着至关重要的影响。 首先,JVM内存管理涉及的内存空间主要分为方法区(Method Area)、堆(Heap)、本地方法栈...

    JVM内存管理及调优

    **JVM内存管理及调优** Java虚拟机(JVM)是Java程序运行的基础,它为Java应用程序提供了运行环境。JVM内存管理是优化Java应用性能的关键环节,涉及到内存分配、垃圾回收以及内存溢出等问题。毕玄,一位在淘宝有着...

    JVM内存管理学习笔记

    《JVM内存管理学习笔记》 在Java世界中,JVM(Java Virtual Machine)是运行所有Java应用程序的核心。深入理解JVM内存管理对于优化程序性能、预防和解决内存泄漏问题至关重要。本文将从JVM内存模型、内存区域划分、...

    JVM内存管理和JVM垃圾回收

    理解JVM内存管理和垃圾回收机制对于优化Java应用的性能至关重要。开发者可以根据应用的需求和特点,通过调整JVM参数来选择合适的内存配置和垃圾回收策略。同时,使用如JVisualVM等工具进行实时监控和分析,可以帮助...

    JVM内存管理、调优与监控考据

    总的来说,JVM内存管理、调优与监控是一项综合性的技术工作,需要对JVM内部机制有深入理解,并结合具体应用场景进行细致的分析和实践。由于JVM的实现可能存在差异,且规范与实现之间存在一定的不一致性,因此,进行...

    JVM内存管理和垃圾回收

    理解JVM内存管理和垃圾回收机制对于优化Java应用程序性能至关重要,开发者可以通过调整JVM参数来定制适合应用需求的内存配置和垃圾回收策略。例如,设置新生代和老年代的大小、选择合适的垃圾回收器、设定最大暂停...

    JVM内存管理白皮书[借鉴].pdf

    在《JVM内存管理白皮书》中,深入探讨了JVM如何处理内存分配、垃圾收集以及各种收集器的工作原理。以下是对该白皮书部分内容的详细解读: 1. 显式与自动内存管理: 在传统的C++等语言中,程序员需要手动进行内存...

    从JVM内存管理的角度谈谈静态方法和静态属性

    理解JVM内存管理和静态成员的工作原理对于优化Java程序的性能至关重要。合理的对象创建、内存使用以及静态成员的恰当运用,都可以帮助提升程序效率并降低内存消耗。在编写代码时,应根据实际需求选择静态或非静态...

    JVM内存管理面试常见问题全解.doc

    JVM 内存管理面试常见问题全解 JVM 内存管理是 Java 程序员必须掌握的重要知识点,本文将对 JVM 内存管理的面试常见问题进行全解。 一、什么是 JVM Java Virtual Machine(Java 虚拟机)是 Java 程序实现跨平台的...

    JVM内存管理和垃圾回收.pdf

    Java虚拟机(JVM)内存管理和垃圾回收是Java编程中至关重要的概念,它涉及到...总之,JVM内存管理和垃圾回收是优化Java应用性能的关键。了解这些概念并正确配置JVM参数,可以帮助开发者创建更高效、更稳定的软件系统。

    JVM内存管理知识思维导图.png

    JVM内存管理知识思维导图.png

    JVM内存管理-GC模型-编写GC友好的代码.pdf

    ### JVM内存管理与GC模型详解 #### 一、引言 在现代软件开发中,Java虚拟机(JVM)作为一种广泛使用的平台,其内部机制尤其是内存管理和垃圾收集(GC)模型,对提升程序性能和稳定性至关重要。本文将深入探讨Sun ...

    JVM内存管理和垃圾回收参考.pdf

    Java虚拟机(JVM)内存管理和...总结来说,JVM内存管理和垃圾回收是一个复杂而精细的过程,涉及多种策略和算法,旨在高效利用内存,减少应用暂停时间,并防止内存泄漏。理解和掌握这些原理对优化Java应用性能至关重要。

Global site tag (gtag.js) - Google Analytics