在已经发布的Oracle JDK7 RC(JDK7 build 147)里,HotSpot VM仍然有PermGen,但许多原本存储在PermGen里的东西已经挪到了别的地方。
离HotSpot彻底移除PermGen的一天已经越来越近。本来PermGen就
不是一个JVM完整不可分割的一部分,去了就去了呗。正好把许多同学们对PermGen的误解给扭过来
这草稿压箱底够久了,虽然还是乱七八糟的但还是先发出来吧,方便大家搜资料。
请重点关注
JEP 122: Remove the Permanent Generation。这是移除PermGen的官方提案。
=========================================================================
Paul Hohensee 写道
Yes, the permgen is going away anyway.
Interned Strings and class static variables have been moved to the regular Java heap,
and Symbols into malloc'ed memory in hs21 (the current development version).
The rest of the metadata will go into per classloader+classes-it-loads arenas, one
per classloader. See allocation.* for arena implementation. You'll note that an
arena consists of fixed-sized malloc'ed chunks. The current plan is to dump these
into the CDS archive, though whether we'll make them relocatable or not is up in
the air. In theory, it should be possible to map the chunks at their old addresses
in a new process, because the space was available when the archive was created.
We might do what Linux does with shared libs, namely have a preferred address
and relocate if we can't get that address.
Bug 6964458: Reimplement class meta-data storage to use native memory
=========================================================================
时间线
2010-01-27
Oracle终于得以正式收购Sun。在新闻发布会上,
Oracle + Sun: Transforming the IT Industry
Thomas Kurian做了题为“Software Strategy ”的主题演讲 (
演示稿下载)
其中在5:00左右,他提到了关于Java SE的展望,
引用
·HotSpot and JRockit are strategic JVMs
- Converge best features of HotSpot and JRockit
- Management and Real-time Monitoring
- Run natively on Hypervisors
-
Optimize/Remove Permgen
- Thread Local, Server Class Garbage Collection
- NUMA Compiler Optimization for Multi-Cores
这里明确指出Oracle计划将HotSpot与JRockit合并为单一的高性能JVM,并准备移除前者中的“permanent generation”。
相关评论:
InfoQ: Perspectives on the Conclusion of the Oracle - Sun Acquisition
这则新闻里有
Allex Miller对PermGen改进的评论:
Allex Miller 写道
The permgen improvement is really needed to address a problem that has been getting worse with dynamic languages running on the JVM. Many of these languages like Groovy or JRuby dynamically generate large numbers of small classes at execution time to provide the dynamic behavior. These classes pollute the special "permgen" parts of Java memory and are difficult or impossible to reclaim, causing significant memory problems. The JSR 292 invokedynamic work is addressing some of this problem in another way by allowing dynamic languages to directly link call sites at runtime, avoiding the need to generate many of those internal classes at all.
2010-10-03
JavaOne 2010上,题为“Oracle's JVM Strategy”的演讲同样提到要将HotSpot与JRockit合并到一起,并透露了更多细节:以HotSpot为主,将JRockit一些优秀的部分移植到HotSpot中。其中,同样提到了要移除“permanent generation”。
Henrik Ståhl: Oracle's JVM Strategy (
演示稿下载)
引用
·No artificial class metadata size limit
- App servers load or reload an unpredictable number of classes, often exceeding fixed size bounds
-
Eliminate the Permanent Generation, move metadata to native memory
- Metadata size limited by virtual address space size
2010-11-03
QCon San Francisco 2010上,Adam Messinger演讲同样提到了这个话题
The Road Ahead for Java (
演示稿下载)
2010-06-25
Bug ID 6964458: Reimplement class meta-data storage to use native memory
引用
Change the implementation of the storage for class meta-data in hotspot (klasses) to
use native memory.
Posted Date : 2010-06-25 22:50:22.0
2010-10-08
Bug ID 6990754: Use native memory and reference counting to implement SymbolTable
引用
As designed now, customers of Hotspot have to specify a fixed size for the permanent generation, which is a part of the Java heap that holds the VM's representation of the classfiles and other types in a java program. This is called "metadata" within hotspot. If there are a lot of classes loaded, the JVM can throw OutOfMemoryError for the permanent generation when there is plenty of Java heap space and native C heap space available. The customer would then need to restart the VM with a larger MaxPermSize parameter.
One of the solutions to this problem is to use native C memory for the VM's representation of the Java program. This is currently our chosen solution. The SymbolTable and associated symbols are one type in the JVM that needs to move into native memory, from permgen. The symbols are shared among class loaders so need to be reference counted so that when unreferenced, they are freed.
This work supports bugid 6964458
Posted Date : 2010-10-08 20:24:43.0
2010-11-05
Request for review (XL) 6990754: Use native memory and reference counting to implement SymbolTable
http://bugs.sun.com/view_bug.do?bug_id=7019689 << 关联bug
http://bugs.sun.com/view_bug.do?bug_id=7019165 << 关联bug
Bug ID: 7019165
Votes 0
Synopsis Incorrect symbols in pstack output after SymbolTable changes
Category hotspot:runtime_system
Reported Against
Release Fixed hs21(b05), 7(b135) (Bug ID:2208133)
State 11-Closed, Unverified, bug
Priority: 3-Medium
Related Bugs 6990754
Submit Date 11-FEB-2011
2011-01-27
HotSpot要干掉PermGen了…
OpenJDK 7/HotSpot revision 3582bf76420e (changeset 2059): 6990754: Use native memory and reference counting to implement SymbolTable
引用
6990754: Use native memory and reference counting to implement SymbolTable
Summary: move symbols from permgen into C heap and reference count them
Reviewed-by: never, acorn, jmasa, stefank
第一个code push已经上OpenJDK 7了,
2011-02-10
JDK7 build 129
JDK7 build 129里的HotSpot 21已经开始移除PermGen,改为引用计数方式在native heap上管理SymbolTable
所以现在在HotSpot中的oop继承结构中,老的
symbolOopDesc已经消失,取而代之的是新的
Symbol类。
Jon Masamitsu在
hotspot-dev邮件列表里提到
JDK7发布前可能来不及完成将PermGen移除的工作
Bug ID 7017732: move static fields into Class to prepare for perm gen removal
引用
Currently static fields are stored in the instanceKlass but when those are moved into native memory we'd have to have a new card mark strategy for static fields. This could be something like setting a flag in the instanceKlass and then rescanning every klass during a GC which seems expensive or marking the card for the java.lang.Class then making sure to scan the instanceKlass when scanning the Class. If we move them into the Class then almost all the existing machinery works exactly as it always has. The only execution difference is which constant is materialized for the field access.
Posted Date : 2011-02-07 21:49:13.0
引用
http://hg.openjdk.java.net/jdk7/hotspot-gc/hotspot/rev/c7f3d0b4570f
Posted Date : 2011-03-19 02:15:44.0
7017732: move static fields into Class to prepare for perm gen removal
Reviewed-by: kvn, coleenp, twisti, stefank
Currently static fields are stored in the instanceKlass but when those
are moved into native memory we'd have to have a new card mark
strategy for static fields. This could be something like setting a
flag in the instanceKlass and then rescanning every klass during a GC
which seems expensive or marking the card for the java.lang.Class then
making sure to scan the instanceKlass when scanning the Class. If we
move them into the Class then almost all the existing machinery works
exactly as it always has. The only execution difference is which
constant is materialized for the field access.
Most of the machinery for static fields is now over in
javaClasses.cpp. The bootstrap had to change slightly since we don't
have Class until we've loaded a few classes but it all fits into the
existing mirror creation logic. I also only create mirrors for real
Java classes whereas previously we also created them for internal
klasses we create.
The main implementation oddity is that java.lang.Class instances are
now variably sized. This required a small change in size_given_klass
and a new instanceMirrorKlass to handle visiting the oops in them.
Performance is unchanged. Tested with ctw, runthese, nsk jvmti tests
and jbb with the various collectors.
Posted Date : 2011-03-22 03:22:38.0
经过这个修改后,java.lang.Class就变成HotSpot VM里的一个特例了:虽然它是Java对象(而不是数组),但它的大小却是可变的(像数组而不像普通对象)。
关联的一个bug:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7030435
Some oop_oop_iterate_m() methods iterate outside of specified memory bounds
Bug ID 6962931: move interned strings out of the perm gen
引用
Interned strings are currently stored in the permanent generation. A new approach for managing meta-data is being designed and it requires interned strings to live elsewhere in the the heap (young gen and/or old gen).
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7032129
<< 关联bug
引用
The interned string changes allow interned strings to live in main heap instead of only perm so we can allocate significantly more interned strings before running out of heap.
The use of as_unicode_string in StringTable::verify creates a lot of native memory pressure during the verify since we allocate as much space here as there are char[]s interned. Maybe the code should just get a raw pointer to the char array or there should be a new routine that computes the hash directly from the array. A ResourceMark in the inner loop would work too.
Posted Date : 2011-03-29 17:09:03.0
http://hg.openjdk.java.net/jdk7/hotspot-comp/hotspot/rev/352622fd140a
Posted Date : 2011-04-01 00:29:39.0
7032129: Native memory usage grow unexpectedly for vm/oom/*InternedString tests
Reviewed-by: kvn, kamg, jcoomes
StringTable::verify uses as_unicode_string to verify the hash code we
keep in the table but the only resource mark is outside the loop.
This means that verification makes a copy of the entire StringTable in
a resource area. Now that interned strings aren't in perm the
StringTable can become as large as the Java heap which means
verification can overflow the address space. The fix is to compute
the hash directly from the char[] instead of making a copy. I moved
the hash_string logic into java_lang_String and updated the users
appropriately. Tested with test case that allocates interned strings
until we run out of heap.
Posted Date : 2011-04-01 03:59:50.0
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=8003421
8003421: NPG: Move oops out of InstanceKlass into mirror
引用
After permgen removal, the only oops that need to be walked in class metadata are in InstanceKlass besides mirrors are protection_domain, signers, init_lock. If these fields are moved to the mirror there is no increase in overall footprint. Also these fields can be card marked when modified because mirrors generally get promoted to tenured early, so that young collections don't need to look at these in our metadata (only mirrors).
This would be supportive of MVM because the mirror and these fields cannot be shared between classes so if the InstanceKlass is shared, these things are kept separately in an array indexed by task id. If these things were in the mirror, we'd only have to worry about the mirror in this array. The init_lock had to be virtualized in the MVM prototype. We had extra code that would lock the per-task information as an oop, so this would also be supportive of that.
In javaClasses.hpp there is a mechanism for injecting fields into our known Java objects, so I don't think this is difficult.
=========================================================================
Java虚拟机规范第二版提到:
3.5.4 Method Area
The Java Virtual Machine Specification, Second Edition 写道
3.5.4 Method Area
The Java virtual machine has a method area that is shared among all Java virtual machine threads. The method area is analogous to the storage area for compiled code of a conventional language or analogous to the "text" segment in a UNIX process. It stores per-class structures such as the runtime constant pool, field and method data, and the code for methods and constructors, including the special methods
(§3.9) used in class and instance initialization and interface type initialization.
The method area is created on virtual machine start-up. Although the method area is logically part of the heap, simple implementations may choose not to either garbage collect or compact it. This version of the Java virtual machine specification does not mandate the location of the method area or the policies used to manage compiled code. The method area may be of a fixed size or may be expanded as required by the computation and may be contracted if a larger method area becomes unnecessary. The memory for the method area does not need to be contiguous.
A Java virtual machine implementation may provide the programmer or the user control over the initial size of the method area, as well as, in the case of a varying-size method area, control over the maximum and minimum method area size.
The following exceptional condition is associated with the method area:
·If memory in the method area cannot be made available to satisfy an allocation request, the Java virtual machine throws an OutOfMemoryError.
The Java HotSpot Performance Engine Architecture
引用
Reflective Data are Represented as Objects
Classes, methods, and other internal reflective data are represented directly as objects on the heap (although those objects may not be directly accessible to Java technology-based programs). This not only simplifies the VM internal object model, but also allows classes to be collected by the same garbage collector used for other Java programming language objects.
HotSpot Runtime Overview
引用
Class Metadata in HotSpot
Class loading creates either an instanceKlass or an arrayKlass in the GC permanent generation. The instanceKlass refers to a java mirror, which is the instance of java.lang.Class mirroring this class. The VM C++ access to the instanceKlass is via a klassOop.
Storage Management
引用
The Permanent Generation
In addition to the objects created by the Java application, there are objects created and used by the HotSpot virtual machine whose storage it is convenient to have allocated and recovered by the storage manager. To avoid confusing things, such objects are allocated in a separate generation, the so-called “permanent” generation. In fact, the objects in it are not “permanent”, but that's what it has been called historically. For example, information about loaded classes is stored in the permanent generation, and recovered when those classes are no longer reachable from the application.
Troubleshooting Guide for Java SE 6 with HotSpot VM
引用
2.7.4 Getting Information on the Permanent Generation
The permanent generation is the area of heap that holds all the reflective data of the virtual machine itself, such as class and method objects (also called “method area” in The Java Virtual Machine Specification). This area also holds internalized strings.