DirectMemory 容量可通过 -XX:MaxDirectMemorySize
指定,如果不指定,则默认与 Java 堆最大值( -Xmx
指定)一样,下面程序利用 DirectByteBuffe 模拟直接内存溢出的情况
Java 堆用于存储对象实例,只要不断地创建对象,并且保证 GC Roots 到对象之间有可达路径来避免垃圾回收机制清除这些对象,则在对象数量到达最大堆的容量限制后就会产生内存溢出异常。因此我们用编写如下代码来模拟内存溢出
Java 永久代是非堆内存的组成部分,用来存放类名、访问修饰符、常量池、字段描述、方法描述等,因运行时常量池是方法区的一部分,所以这里也包含运行时常量池。我们可以通过 jvm 参数 -XX:PermSize=10M -XX:MaxPermSize=10M
来指定该区域的内存大小,-XX:PermSize
默认为物理内存的 1/64 ,-XX:MaxPermSize
默认为物理内存的 1/4 。String.intern()
方法是一个 Native 方法,它的作用是:如果字符串常量池中已经包含一个等于此 String 对象的字符串,则返回代表池中这个字符串的 String 对象;否则,将此 String 对象包含的字符串添加到常量池中,并且返回此 String 对象的引用。在 JDK 1.6 及之前的版本中,由于常量池分配在永久代内,我们可以通过 -XX:PermSize
和 -XX:MaxPermSize
限制方法区大小,从而间接限制其中常量池的容
<!-- more -->
标记,标记之前内容为摘要
关于 Java 的垃圾收集( Garbage Collection,GC ),Java 运行时区域的各个部分,程序计数器、虚拟机栈、本地方法栈 3 个区域随线程而生,随线程而灭;栈中的栈帧随着方法的进入和退出而有条不絮的执行者岀栈和入栈操作。
每个栈帧中分配多少内存基本上实在类结构确定下来时就已知的,因此在这几个区域内存的分配和回收都具有确定性,就不需要过多考虑回收的问题,因为在方法结束或者线程结束时,内存就自然跟着回收了。既然 Java 的内存回收已经如此智能,我们为什么还有继续了解 GC 和内存分配呢?
在可达性分析算法中不可达的对象,也并非是“非死不可”的,一个对象死亡,至少要经历两次标记过程:如果对象在进行可达性分析后发现没有与 GC Roots 相连接的引用链,那它将会被第一次标记并且进行一次筛选,筛选的条件是此对象是否有必要执行 finalize ( )
方法。当对象没有覆盖 finalize ( )
方法,或者 finalize ( )
方法已经被虚拟机调用过,虚拟机将这两种情况都视为“没有必要执行”。
很多人认为方法区(或者 HotSpot 虚拟机中的永久代)是没有垃圾收集的,Java虚拟机规范中确实说过可以不要求虚拟机在方法区实现垃圾收集,而且在方法区中进行垃圾收集的“性价比”一般比较低:在堆中,尤其是在新生代中,常规应用进行一次垃圾收集一般可以回收 70%~95% 的空间,而永久代的垃圾收集效率远低于此。
Java 虚拟机规范中对垃圾收集器应该如何实现并没有任何规定,因此不同的厂商、不同版本的虚拟机所提供的垃圾收集器都可能会有很大差别,并且一般都会提供参数供用户根据自己的应用特点和要求组合出各个年代所使用的收集器。下面是 JDK 1.7 Update 14之后的 HotSpot 虚拟机包含的所有收集器:
<!-- more -->
标记,标记之前内容为摘要
<!-- more -->
标记,标记之前内容为摘要