Presenting the Permanent Generation

本文深入探讨了Java虚拟机中永久代的概念及其重要性。解释了为何要将类信息存放在永久代而非堆中,并讨论了永久代包含的内容以及其对垃圾回收的影响。

Presenting the Permanent Generation

By jonthecollector on Nov 28, 2006

Have you ever wondered how the permanent generation fits into our generational system? Ever been curious about what’s in the permanent generation. Are objects ever promoted into it? Ever promoted out? We’ll you’re not alone. Here are some of the answers.

Java objects are instantiations of Java classes. Our JVM has an internal representation of those Java objects and those internal representations are stored in the heap (in the young generation or the tenured generation). Our JVM also has an internal representation of the Java classes and those are stored in the permanent generation. That relationship is shown in the figure below.

permGenObj

The internal representation of a Java object and an internal representation of a Java class are very similar. From this point on let me just call them Java objects and Java classes and you’ll understand that I’m referring to their internal representation. The Java objects and Java classes are similar to the extent that during a garbage collection both are viewed just as objects and are collected in exactly the same way. So why store the Java objects in a separate permanent generation? Why not just store the Java classes in the heap along with the Java objects?

Well, there is a philosophical reason and a technical reason. The philosophical reason is that the classes are part of our JVM implementation and we should not fill up the Java heap with our data structures. The application writer has a hard enough time understanding the amount of live data the application needs and we shouldn’t confuse the issue with the JVM’s needs.

The technical reason comes in parts. Firstly the origins of the permanent generation predate my joining the team so I had to do some code archaeology to get the story straight (thanks Steffen for the history lesson).

Originally there was no permanent generation. Objects and classes were just stored together.

Back in those days classes were mostly static. Custom class loaders were not widely used and so it was observed that not much class unloading occurred. As a performance optimization the permanent generation was created and classes were put into it. The performance improvement was significant back then. With the amount of class unloading that occur with some applications, it’s not clear that it’s always a win today.

It might be a nice simplification to not have a permanent generation, but the recent implementation of the parallel collector for the tenured generation (aka parallel old collector) has made a separate permanent generation again desirable. The issue with the parallel old collector has to do with the order in which objects and classes are moved. If you’re interested, I describe this at the end.

So the Java classes are stored in the permanent generation. What all does that entail? Besides the basic fields of a Java class there are

  • Methods of a class (including the bytecodes)
  • Names of the classes (in the form of an object that points to a string also in the permanent generation)
  • Constant pool information (data read from the class file, see chapter 4 of the JVM specification for all the details).
  • Object arrays and type arrays associated with a class (e.g., an object array containing references to methods).
  • Internal objects created by the JVM (java/lang/Object or java/lang/exception for instance)
  • Information used for optimization by the compilers (JITs)

That’s it for the most part. There are a few other bits of information that end up in the permanent generation but nothing of consequence in terms of size. All these are allocated in the permanent generation and stay in the permanent generation. So now you know.

This last part is really, really extra credit. During a collection the garbage collector needs to have a description of a Java object (i.e., how big is it and what does it contain). Say I have an object X and X has a class K. I get to X in the collection and I need K to tell me what X looks like. Where’s K? Has it been moved already? With a permanent generation during a collection we move the permanent generation first so we know that all the K’s are in their new location by the time we’re looking at any X’s.

How do the classes in the permanent generation get collected while the classes are moving? Classes also have classes that describe their content. To distinguish these classes from those classes we spell the former klasses. The classes of klasses we spell klassKlasses. Yes, conversations around the office can be confusing. Klasses are instantiation of klassKlasses so the klassKlass KZ of klass Z has already been allocated before Z can be allocated. Garbage collections in the permanent generation visit objects in allocation order and that allocation order is always maintained during the collection. That is, if A is allocated before B then A always comes before B in the generation. Therefore if a Z is being moved it’s always the case that KZ has already been moved.

And why not use the same knowledge about allocation order to eliminate the permanent generations even in the parallel old collector case? The parallel old collector does maintain allocation order of objects, but objects are moved in parallel. When the collection gets to X, we no longer know if K has been moved. It might be in its new location (which is known) or it might be in its old location (which is also known) or part of it might have been moved (but not all of it). It is possible to keep track of where K is exactly, but it would complicate the collector and the extra work of keeping track of K might make it a performance loser. So we take advantage of the fact that classes are kept in the permanent generation by collecting the permanent generation before collecting the tenured generation. And the permanent generation is currently collected serially.

内容概要:本文提出了一种针对大规模电动汽车接入电网的双层优化调度策略,并基于IEEE33节点系统进行了建模与仿真分析,配套提供了完整的Matlab代码实现。该策略构建了上层电网运行优化与下层电动汽车充电调度的双层协同模型,综合考虑电网负荷削峰填谷、电压稳定性维持以及电动汽车用户充电需求满足等多重目标,采用先进的优化算法实现对电动汽车集群的智能有序调度。研究详细阐述了双层模型的构建逻辑、目标函数设计、约束条件设定及迭代求解流程,有效降低了电网峰谷差,提升了配电系统对可再生能源的消纳能力,兼具扎实的理论深度与明确的工程应用前景。; 适合人群:电气工程、电力系统及其自动化、能源系统优化等相关专业的研究生、科研人员以及从事智能电网、电动汽车调度、分布式能源管理等领域工作的工程师和技术人员。; 使用场景及目标:①深入研究高比例电动汽车接入对配电网运行特性的影响机制;②掌握电力系统双层优化建模方法及其在实际系统中的求解技巧;③实现电动汽车集群的协同调度与车网互动(V2G)优化控制;④作为撰写学术论文、开展课题研究或复现高水平期刊成果的技术参考与代码基础。; 阅读建议:建议读者结合所提供的Matlab代码逐行理解双层优化模型的数学表达与程序实现细节,重点剖析上下层模型之间的信息交互机制与收敛判据,可通过调整电动汽车渗透率、充电行为参数或引入分布式电源等场景进行拓展性仿真,以深化对智能调度策略适应性的认识。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值