和内存释放(主要是GC)有关的话题。

  ★JVM的内存?

  在Java虚拟机规范中(具体章节请看“这里 ”),提及了如下几种类型的内存空间:

  ◇栈内存(Stack):每个线程私有的。

  ◇堆内存(Heap):所有线程公用的。

  ◇方法区(MethodArea):有点像以前常说的“进程代码段”,这里面存放了每个加载类的反射信息、类函数的代码、编译时常量等信息。

  ◇原生方法栈(Native Method Stack):主要用于JNI中的原生代码,平时很少涉及。

?

  ★垃圾回收机制简介?

  其实Java虚拟机规范中并未规定垃圾回收的相关细节。垃圾回收具体该怎么搞,完全取决于各个JVM的设计者。所以,不同的JVM之间,GC的行为可能会有一定的差异。下面咱拿SUN官方的JVM来简单介绍一下GC的机制。

  ◇啥时候进行垃圾回收?

  一般情况下,当JVM发现堆内存比较紧张、不太够用时,它就会着手进行垃圾回收工作。但是大伙儿要认清这样一个残酷的事实:JVM进行GC的时间点是无法精确预知的。因为GC启动的时刻会受到各种运行环境因素的影响,随机性太大。

  虽说咱们无法精确预知,但假如你想知道每次垃圾回收执行的情况,还是蛮方便的。可以通过JVM的命令行参数“-XX:+PrintGC”把相关信息打印出来。

  另外,调用System.gc()只是建议JVM进行GC。至于JVM到底会不会做,那就不好说啦。通常不建议自己手动调用System.gc(),还是让JVM自行决定比较好。另外,使用JVM命令行参数“-XX:+DisableExplicitGC”可以让System.gc()不起作用。

  ◇谁来负责垃圾回收?

  一般情况下,JVM会有一个或多个专门的垃圾回收线程,由它们负责清理回收垃圾内存。

  ◇如何发现垃圾对象?

  垃圾回收线程会从“根集(Root Set)”开始进行对象引用的遍历。所谓的“根集”,就是正在运行的线程中,可以访问的引用变量的集合(比如所有线程当前函数的参数和局部变量、当前类的成员变量等等)。垃圾回收线程先找出被根集直接引用的所有对象(不妨叫集合1),然后再找出被集合1直接引用的所有对象(不妨叫集合2),然后再找出被集合2直接引用的所有对象......如此循环往复,直到把能遍历到的对象都遍历完。

  凡是从根集通过上述遍历可以到达的对象,都称为可达对象或有效对象;反之,则是不可达对象或失效对象(也就是垃圾)。

  ◇如何清理/回收垃圾?

  通过上述阶段,就把垃圾对象都找出来。然后垃圾回收线程会进行相应的清理和回收工作,包括:把垃圾内存重新变为可用内存、进行内存的整理以消除内存碎片、等等。这个过程会涉及到若干算法,有爱好的同学可以参见“这里”。限于篇幅,咱就不深入聊了。

  ◇分代

  早期的JVM是不采用分代技术的,所有被GC管理的对象都存放在同一个堆里面。这么做的缺点比较明显:每次进行GC都要遍历所有对象,开销很大。其实大部分的对象生命周期都很短(短命对象),只有少数对象比较长寿;在这些短命对象中,又只有少数对象占用的内存空间大;其它大量的短命对象都属于小对象(很符合二八原理 )。

   有鉴于此,从JDK 1.2之后,JVM开始使用分代的垃圾回收(Generational GarbageCollection)。JVM把GC相关的内存分为年老代(Tenured)和年轻代(Nursery)、持久代(Permanent,对应于JVM规范的方法区)。大部分对象在刚创建时,都位于年轻代。假如某对象经历了几轮GC还活着(大龄对象),就把它移到年老代。另外,假如某个对象在创建时比较大,可能就直接被丢到年老代。经过这种策略,使得年轻代总是保存那些短命的小对象。在空间尺寸上,年轻代相对较小,而年老代相对较大。

  因为有了分代技术,JVM的GC也相应分为两种:主要收集(Major Collection)和次要收集(MinorCollection)。主要收集同时清理年老代和年轻代,因此开销很大,不常进行;次要收集仅仅清理年轻代,开销很小,经常进行。

?

  ★GC对性能会有啥影响??

  刚才介绍了GC的大致原理,那GC对性能会造成哪些影响捏?主要有如下几个方面:

  ◇造成当前运行线程的停顿

  早期的GC比较弱智。在它工作期间,所有其它的线程都被暂停(以免影响垃圾回收工作)。等到GC干完活,其它线程再继续运行。所以,早期JDK的GC一旦开始工作,整个程序就会陷入假死状态,失去各种响应。

  经过这些年的技术改进(包括采用分代技术),从JDK1.4开始,GC已经比较精明了。在它干活期间,只是偶然暂停一下其它线程的运行(从长时间假死变为暂时性休克)。

  ◇遍历对象引用的开销

  试想假如JVM中的对象很多,那遍历完所有可达对象肯定是比较费劲的工作,这个开销可不小。

  ◇清理和回收垃圾的开销

  遍历完对象引用之后,对垃圾的清理和回收也有较大的开销。这部分开销可能包括复制内存块、更新对象引用等等。

?

  ★几种收集器?

  ◇两个性能指标

  因为今天聊的是性能的话题,必然会提到衡量GC性能的两个重要指标:吞吐量(Throughput)和停顿时间(PauseTime)。吞吐量这个词不是很直观,解释一下:就是JVM不用于GC的时间占总时间的比率。吞吐量是越大越好,停顿时间是越小越好。

  不同的应用程序对这两个指标的关注点不一样(后面具体会说),也就是所谓的“众口难调”。很多JVM厂商为了迎合“众口”,不得不提供多种几种垃圾收集器供使用者选择。不同的收集器,采用的收集策略是不一样的,下面具体介绍。

  ◇串行收集器(Serial Collector)

  使用命令行选项“-XX:+UseSerialGC”指定。

  这种收集器是最传统的收集器。它使用单线程进行垃圾回收,对于单CPU机器比较合适。另外,小型应用或者对上述两个指标没有非凡要求的,可以使用串行收集器。

  ◇并行收集器(Parallel Throughput Collector)

  顾名思义,这种收集器使用多个线程进行垃圾回收以达到高吞吐量。垃圾回收线程的数量通过命令行选项“-XX:ParallelGCThreads=n”指定。可以设置该数值以便充分利用多CPU/多核。

  当使用命令行选项“-XX:+UseParallelGC”时:它会针对年轻代使用多个垃圾回收线程,对年老代依然使用单个线程的串行方式。此选项最早在JDK1.5引入。

  当使用命令行选项“-XX:+UseParallelOldGC”时:它针对年轻代和年老代都使用多个垃圾回收线程的方式。不过此选项从JDK1.6才开始引入。

  ◇并发收集器(Concurrent Low Pause Collector)

  使用命令行选项“-XX:+UseConcMarkSweepGC”指定。

  这种收集器优先保证程序的响应。它会尽量让垃圾回收线程和应用自身的线程同时运行,从而降低停顿时间。此选项从JDK1.4.1开始支持。

  ◇增量收集器(Incremental Collector)

  自从JDK 1.4.2以来,SUN官方就停止维护该收集器了。所以俺就节省点口水,不多说了。

?

  ★如何降低GC的影响??

  ◇尽量减少堆内存的使用

  由于GC是针对存储在堆内存的对象进行的。咱们假如在程序中减少引用对象的分配(也就相应降低堆内存分配),那对于提高GC的性能是很有帮助滴。上次“字符串过滤实战”的帖子给出了一个例子,示范了如何通过降低堆内存的分配次数来提升性能。

?

  ◇设置合适的堆内存大小

  JVM的堆内存是有讲究的,不能太大也不能太小。假如堆内存太小,JVM老是感觉内存不够用,可能会导致频繁进行垃圾回收,影响了性能;假如堆内存太大,以至于操作系统的大部分物理内存都被JVM自个儿霸占了,那可能会影响其它应用程序甚至操作系统本身的性能。

  另外,年轻代的大小(或者说年轻代与年老代的比值)对于GC的性能也有明显影响。假如年轻代太小,可能导致次要收集很频繁;假如年轻代太大,导致次要收集的停顿很明显。

  JVM提供了若干和堆内存大小相关的命令行选项,具体如下:

------------------------------

-Xms  设置初始堆内存

-Xmx  设置最大堆内存

-Xmn  设置年轻代的大小

-XX:NewRatio=n  设置年轻代与年老代的比例为“n”

-XX:NewSize=n  设置年轻代大小为“n”

------------------------------

  一般情况下,JVM的默认参数值已经够用。所以没事儿别轻易动用上述选项。假如你非调整不可,一定要做深入的性能对比测试,保证调整后的性能确实优于默认参数值。

?

  ◇吞吐量和停顿的取舍

  前面提到了不同应用的众口难调。常见的口味有两种:(1)看重吞吐量,对停顿时间无所谓;(2)侧重于停顿时间。

  对于某些在后台的、单纯运算密集型的应用,属于第一种。比如某些科学计算的应用。这时候建议使用并行收集器。

  对于涉及用户UI交互的、实时性要求比较高、程序需要快速响应的,属于第二种。比如某些桌面游戏、某些电信交换系统。这时候建议使用并发收集器。

?

  ★相关的参考资料?

  ◇GC调优资料

  SUN官方提供了若干关于JVM垃圾回收调优的说明文档,JDK 1.4.2请看“这里 ”;JDK 1.5请看“这里 ”;JDK1.6请看“这里 ”。

  ◇JVM命令行选项说明

  这是SUN公司内的某个有心人整理的各种命令行参数大全,在“这里 ”。包括有每个参数所适用的JDK版本。

  ◇虚拟机规范

  “这里 ”是SUN官方的JVM规范。

JAVA内存释放机制相关推荐

  1. java中创建类的时候有没有分配内存,你必须了解的java内存管理机制(一)-内存分配...

    前言 在上一篇文章中,我们花了较大的篇幅去介绍了JVM的运行时数据区,并且重点介绍了栈区的结构及作用,相关内容请猛戳!在本文中,我们将主要介绍对象的创建过程及在堆中的分配方式.from 你必须了解的j ...

  2. C++ 中 map 容器的内存释放机制及内存碎片管理

    C++ 中 map 容器的内存释放机制及内存碎片管理 C++ 中的容器很好用,比如 vector, map 等,可以动态扩容,自己管理内存,不用用户关心,但是在某些极端情况下,如果内存比较紧张的情况下 ...

  3. Java内存回收机制基础[转]

    原文链接:http://blog.jobbole.com/37273/ 在Java中,它的内存管理包括两方面:内存分配(创建Java对象的时候)和内存回收,这两方面工作都是由JVM自动完成的,降低了J ...

  4. 浅析java内存管理机制

    内存管理是计算机编程中的一个重要问题,一般来说,内存管理主要包括内存分配和内存回收两个部分.不同的编程语言有不同的内存管理机制,本文在对比C++和java语言内存管理机制的不同的基础上,浅析java中 ...

  5. 2.Java内存回收机制

    一.Java对象在内存引用状态 内存泄露:程序运行过程中,会不断分配内存空间,那些不再使用的内存空间应该即时回收它们,从而保证系统可以再次使用这些内存,如果存在无用的内存没有被回收回来,这就是内存泄漏 ...

  6. java内存管理机制-转载保存有价值的东西

    JAVA 内存管理总结 1. java是如何管理内存的 Java的内存管理就是对象的分配和释放问题.(两部分) 分配 :内存的分配是由程序完成的,程序员需要通过关键字new 为每个对象申请内存空间 ( ...

  7. JAVA内存管理机制

    在Java中,它的内存管理包括两方面:内存分配(创建Java对象的时候)和内存回收,这两方面工作都是由JVM自动完成的,降低了Java程序员的学习难度,避免了像C/C++直接操作内存的危险.但是,也正 ...

  8. java内存管理机制剖析(一)

    最近利用工作之余学习研究了一下java的内存管理机制,在这里记录总结一下. 1.1 java内存区域 当java程序运行时,java虚拟机会将内存划分为若干个不同的数据区域,这些内存区域创建和销毁的时 ...

  9. 【JAVA内存回收】Java 内存回收机制

    下面这个图,很清楚地说明对象在new的时候是怎样开辟内存空间的 其中对象new出来的,是栈内存,变量的开辟是堆内存 Java的一个重要优点就是通过垃圾收集器GC (Garbage Collection ...

最新文章

  1. 利用BP神经网络教计算机识别语音特征信号(代码部分SSR)
  2. readline 库简写版本,测试可用
  3. 【计算理论】计算理论总结 ( 非确定性有限自动机 NFA 转为确定性有限自动机 DFA | 示例 ) ★★
  4. 开启虚拟化技术之旅---1什么是虚拟化?
  5. hdu 4588 Count The Carries 南京邀请赛
  6. node 安装 webpack
  7. 极客先锋 如何生成git的公钥和私钥
  8. 开发环境和运行环境_内网安全运行环境
  9. UIImagePickerController的知识点总结
  10. 2021-09-02spark streaming
  11. Linux - grep命令详解
  12. 用matlab解线性规划题目,用MATLAB软件解线性规划范例
  13. 企业微信应用发送消息
  14. 51单片机:1602液晶显示屏
  15. 使用 Python 制作图片和语音验证码
  16. 雷士灯wifi控制方法_欧普照明 WIFI控制安装使用说明
  17. u盘iso安装服务器系统怎么安装win7系统安装方法,u盘iso安装系统,小猪教您u盘怎么安装win7系统...
  18. 一个屌丝程序员的青春(一三二)
  19. 邢台一中2021年许计勇高考成绩查询,文理Top10!2020邢台高考成绩揭晓...
  20. eos代码阅读笔记09- 石墨烯架构Graphene

热门文章

  1. PHP过滤常用标签的正则表达式
  2. 那一天,那一月,那一年,那一世,那一瞬
  3. 看博客学学Android(二十一)
  4. Windows 部署服务(WDS)基础配置指南 (2008 or 2008R2 Only)
  5. 用cisco设备解决ARP病毒
  6. 安全公司本意告警用户,不料先遭攻击并泄露超50亿个人数据
  7. sonic——可替代Elasticsearch的简单搜索引擎
  8. SSH远程执行命令环境变量问题
  9. linux系统下文件查找
  10. 在Win7旗舰版安装并运行LoadRunner11