最近关注了一下垃圾回收的问题,想了解一下JVM 关于方法区的垃圾回收机制,找了几篇文章,不同的文章从不同角度讲述了一下,嗯。。。 拼凑起来 记录一下, 有些未验证正确性。。。
JVM 方法区
当JVM使用类装载器装载某个类时,它首先要定位对应的class文件,然后读入这个class文件,最后,JVM提取该文件的内容信息,并将这些信息存储到方法区,最后返回一个class实例。上面是对类的装载过程作了个简单的描述,看了上面一段文字,也许你会问:方法区是什么?里面存了哪些内容?下面我们将对方法区作一个详细的描述。
方法区是什么?有哪些特点?
方法区是系统分配的一个内存逻辑区域,是用来存储类型信息的(类型信息可理解为类的描述信息)。方法区主要有以下几个特点:
一.方法区是线程安全的。由于所有的线程都共享方法区,所以,方法区里的数据访问必须被设计成线程安全的。例如,假如同时有两个线程都企图访问方法区中的同一个类,而这个类还没有被装入JVM,那么只允许一个线程去装载它,而其它线程必须等待
二.方法区的大小不必是固定的,JVM可根据应用需要动态调整。同时,方法区也不一定是连续的,方法区可以在一个堆(甚至是JVM自己的堆)中自由分配。
三.方法区也可被垃圾收集,当某个类不在被使用(不可触及)时,JVM将卸载这个类,进行垃圾收集
方法区里存放的是哪些内容?
方法区里存的都是类型信息,也就是类的信息,而类的信息又包括以下内容:
类的全限定名(类的全路径名)
类的直接超类的全限定名(如果这个类是Object,则它没有超类)
这个类是类型(类)还是接口
类的访问修饰符,如public、abstract、final等
所有的直接接口全限定名的有序列表(假如它实现了多个接口)
常量池
字段、方法信息、类变量信息(静态变量) 装载该类的装载器的引用(classLoader)、类型引用(class)
原文地址: http://xtu-tja-163-com.iteye.com/blog/769992
还有一篇 不让转载的:http://blog.youkuaiyun.com/u010571316/article/details/45506567
接下来是关于-XX:+UseParNewGC和
-XX:+UseConcMarkSweepGC两个参数的,看到有一个service启动的时候用了这两个参数,很是不解,于是找了找,以下内容就不是转载的了 算是翻译总结吧。。。
先来看一下这两个参数都是干什么的吧:
-XX:+UseConcMarkSweepGC
这个参数在官网有解释 http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html#generation_sizing.young_gen
The concurrent collector performs most of its work concurrently (i.e., while the application is still running) to keep garbage collection pauses short. It is designed for applications with medium- to large-sized data sets for which response time is more important than overall throughput, since the techniques used to minimize pauses can reduce application performance. The concurrent collector is enabled with the option -XX:+UseConcMarkSweepGC
意思是说: 在保证正常的工作的同时让垃圾回收暂停的时间短一些,主要是用在反应时间比整体吞吐量更重要中大型的数据中,这个技术主要是最小化会影响程序效率的暂停。
-XX:+UseParNewGC
To enable a parallel young generation GC with the concurrent GC add -XX:+UseParNewGC
to the startup. Don't add -XX:+UseParallelGC
with this option.
要在使用并发收集器(concurrent GC也不知道这么翻译对么)的同时启用新生代的并行GC 就要加这个参数,不要加-XX:+UseParallelGC
来自: http://www.petefreitag.com/articles/gctuning/
虽然从上面那篇文章看来,好像两个都要设置的样子,反正我是这样理解的。。。
http://stackoverflow.com/questions/220388/java-concurrent-and-parallel-gc
在这里有个楼主问了同样的问题,然后就有大牛开始回答了,我仔细看了被接受的回答,主要意思是:
-XX:+UseConcMarkSweepGC 这个玩意如果设了,那么 -XX:+UseParNewGC 也是true的,如果不是才需要指定。。。
大牛们的意思就是 设了-XX:+UseConcMarkSweepGC 再设-XX:+UseParNewGC 就没意义了,没准在jdk6还会报错,然后底下也有很多人纷纷表示不需要再设了
然后可以用java -XX:+PrintCommandLineFlags -XX:+UseConcMarkSweepGC -version 试一下java到底设了啥。
大牛说他用的1.6.0_26 就是这样的效果。
以下亲测,分别是两个机器,嗯,随意感受一下:
版本一:
java -XX:+PrintCommandLineFlags -XX:+UseConcMarkSweepGC -version
-XX:+PrintCommandLineFlags -XX:+UseConcMarkSweepGC
java version "1.6.0_07"
Java(TM) SE Runtime Environment (build 1.6.0_07-b06)
版本二:
java -XX:+PrintCommandLineFlags -XX:+UseConcMarkSweepGC -version
-XX:InitialHeapSize=59885760 -XX:MaxHeapSize=958172160 -XX:MaxNewSize=174485504 -XX:MaxTenuringThreshold=6 -XX:OldPLABSize=16 -XX:+PrintCommandLineFlags -XX:+UseCompressedOops -XX:+UseConcMarkSweepGC -XX:+UseParNewGC
java version "1.7.0_79"
Java(TM) SE Runtime Environment (build 1.7.0_79-b15)
哈哈不一样吧。。。 理论联系实际,看来还是要看情况的,估计是从1.60_xx 版本开始就不需要两个一起设置了,之前还是要滴。。。 至于是那个版本,要么去看官网,要么在使用的时候注意一下就好啦。