方法区和运行时常量池溢出

基于R语言的PLS算法实现解读 我们使用"pls"包来执行PLS回归,并提供了相应的源代码。在本文中,我们将详细解读基于R语言的PLS算法的实现过程,并提供相应的源代码。PLS算法的实现可以借助R语言中的"pls"包。该包提供了丰富的函数和工具,用于执行PLS回归、PLS-DA(PLS-Discriminant Analysis)和其他相关任务。除了执行PLS回归,"pls"包还提供了其他功能,例如PLS-DA(用于分类问题)和PLS变量选择等。上述代码将基于输入的X值,使用训练好的PLS模型进行预测,并返回预测结果。 阅读详情

方法区和运行时常量池溢出

由于运行时常量池是方法区的一部分,因此这两个区域的溢出测试就放在一起进行。前面提到JDK 1.7开始逐步“去永久代”的事情,在此就以测试代码观察一下这件事对程序的实际影响。

String.intern()是一个Native方法,它的作用是:如果字符串常量池中已经包含一个等于此String对象的字符串,则返回代表池中这个字符串的String对象;否则,将此String对象包含的字符串添加到常量池中,并且返回此String对象的引用。在JDK 1.6及之前的版本中,由于常量池分配在永久代内,我们可以通过-XX:PermSize和-XX:MaxPermSize限制方法区大小,从而间接限制其中常量池的容量,如代码清单2-6所示。

代码清单2-6 运行时常量池导致的内存溢出异常

  1. /**  
  2.  * VM Args:-XX:PermSize=10M -XX:MaxPermSize=10M 
  3.  * @author zzm  
  4.  */  
  5. public class RuntimeConstantPoolOOM {  
  6.  
  7. public static void main(String[] args) {  
  8. // 使用List保持着常量池引用,避免Full GC回收常量池行为  
  9. List<String> list = new ArrayList<String>();  
  10. // 10MB的PermSize在integer范围内足够产生OOM了  
  11. int i = 0;   
  12. while (true) {  
  13. list.add(String.valueOf(i++).intern());  
  14. }  
  15. }  
  16. }  

运行结果:

  1. Exception in thread "main" java.lang.OutOfMemoryError: PermGen space  
  2. at java.lang.String.intern(Native Method)  
  3. at org.fenixsoft.oom.RuntimeConstantPoolOOM.main(RuntimeConstantPoolOOM.java:18) 

从运行结果中可以看到,运行时常量池溢出,在OutOfMemoryError后面跟随的提示信息是“PermGen space”,说明运行时常量池属于方法区(HotSpot虚拟机中的永久代)的一部分。

而使用JDK 1.7运行这段程序就不会得到相同的结果,while循环将一直进行下去。关于这个字符串常量池的实现问题,还可以引申出一个更有意思的影响,如代码清单2-7所示。

代码清单2-7 String.intern()返回引用的测试

  1. public class RuntimeConstantPoolOOM {  
  2.  
  3.  public static void main(String[] args) {  
  4.  public static void main(String[] args) {  
  5.  String str1 = new StringBuilder("计算机").append("软件").toString();  
  6.  System.out.println(str1.intern() == str1);  
  7.  
  8.  String str2 = new StringBuilder("ja").append("va").toString();  
  9.  System.out.println(str2.intern() == str2);  
  10.  } }  
  11. }  

这段代码在JDK 1.6中运行,会得到两个false,而在JDK 1.7中运行,会得到一个true和一个false。产生差异的原因是:在JDK 1.6中,intern()方法会把首次遇到的字符串实例复制到永久代中,返回的也是永久代中这个字符串实例的引用,而由StringBuilder创建的字符串实例在Java堆上,所以必然不是同一个引用,将返回false。而JDK 1.7(以及部分其他虚拟机,例如JRockit)的intern()实现不会再复制实例,只是在常量池中记录首次出现的实例引用,因此intern()返回的引用和由StringBuilder创建的那个字符串实例是同一个。对str2比较返回false是因为“java”这个字符串在执行StringBuilder.toString()之前已经出现过,字符串常量池中已经有它的引用了,不符合“首次出现”的原则,而“计算机软件”这个字符串则是首次出现的,因此返回true。

方法区用于存放Class的相关信息,如类名、访问修饰符、常量池、字段描述、方法描述等。对于这些区域的测试,基本的思路是运行时产生大量的类去填满方法区,直到溢出。虽然直接使用Java SE API也可以动态产生类(如反射时的GeneratedConstructorAccessor和动态代理等),但在本次实验中操作起来比较麻烦。在代码清单2-8中,笔者借助CGLib直接操作字节码运行时生成了大量的动态类。

值得特别注意的是,我们在这个例子中模拟的场景并非纯粹是一个实验,这样的应用经常会出现在实际应用中:当前的很多主流框架,如Spring、Hibernate,在对类进行增强时,都会使用到CGLib这类字节码技术,增强的类越多,就需要越大的方法区来保证动态生成的Class可以加载入内存。另外,JVM上的动态语言(例如Groovy等)通常都会持续创建类来实现语言的动态性,随着这类语言的流行,也越来越容易遇到与代码清单2-8相似的溢出场景。

代码清单2-8 借助CGLib使方法区出现内存溢出异常

  1. /**  
  2.  * VM Args: -XX:PermSize=10M -XX:MaxPermSize=10M 
  3.  * @author zzm  
  4.  */  
  5. public class JavaMethodAreaOOM {  
  6.  
  7.  public static void main(String[] args) {  
  8.  while (true) {  
  9.  Enhancer enhancer = new Enhancer();  
  10.  enhancer.setSuperclass(OOMObject.class);  
  11.  enhancer.setUseCache(false);  
  12.  enhancer.setCallback(new MethodInterceptor() {  
  13.  public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {  
  14.  return proxy.invokeSuper(obj, args);  
  15.  }  
  16.  });  
  17.  enhancer.create();  
  18.  }  
  19.  }  
  20.  
  21. static class OOMObject {  
  22.  
  23. }  
  24. }  

运行结果:

  1. Caused by: java.lang.OutOfMemoryError: PermGen space  
  2. at java.lang.ClassLoader.defineClass1(Native Method)  
  3. at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632)  
  4. at java.lang.ClassLoader.defineClass(ClassLoader.java:616)  
  5. ... 8 more 

方法区溢出也是一种常见的内存溢出异常,一个类要被垃圾收集器回收掉,判定条件是比较苛刻的。在经常动态生成大量Class的应用中,需要特别注意类的回收状况。这类场景除了上面提到的程序使用了CGLib字节码增强和动态语言之外,常见的还有:大量JSP或动态产生JSP文件的应用(JSP第一次运行时需要编译为Java类)、基于OSGi的应用(即使是同一个类文件,被不同的加载器加载也会视为不同的类)等。

【WRF编译-Lab1】使用自动脚本编译WRF:错误总结 WRF编译过程及错误总结 阅读详情

相关推荐

AJ-Report开源数据大屏存在远程命令执行漏洞

该平台可以通过post方式在validationRules参数对应值中进行命令执行,可以获得服务器权限,登陆管理后台接管大屏。如果被攻击者利用,危害后果十分严重。

swordheart的博客 387

jvm 内存溢出 - 方法区及运行时常量池溢出

Java 永久代是非堆内存的组成部分,用来存放类名、访问修饰符、常量池、字段描述、方法描述等,因运行时常量池是方法区的一部分,所以这里也包含运行时常量池。我们可以通过 jvm 参数-XX:PermSize=10M -XX:MaxPermSize=10M来指定该区域的内存大小,-XX:PermSize默认为物理内存的 1/64 ,-XX:MaxPermSize默认为物理内存的 1/4 。St...

稚枭天卓 598

Excel地理探测器实战:5分钟搞定空间分异性分析(附完整数据集)

本文详细介绍了如何使用Excel地理探测器插件进行空间分异性分析。通过5分钟实战教程,手把手指导数据格式准备、软件操作及四大探测器(分异及因子、交互作用、风险区、生态探测器)的结果解读,帮助规划师、研究者快速验证地理因素对现象分布的影响,大幅降低GIS分析门槛。

peace的博客 607

方法区和运行时常量池溢出:深入理解Java内存管理

方法区和运行时常量池溢出:深入理解Java内存管理

一起coding,一起嗨。 746

手把手教你用Logisim搭建5级流水MIPS CPU(附华中科技计组实验避坑指南)

本文详细介绍了如何使用Logisim从零构建5级流水MIPS CPU,特别针对华中科技大学计算机组成原理实验提供实用指南。内容涵盖单周期CPU过渡、流水线寄存器设计、数据冒险处理等核心环节,并附有实验避坑建议和性能优化技巧,帮助学生高效完成这一挑战性项目。

weixin_42532938的博客 372

【华为OD机试真题】439、精准核酸检测 | 机试真题+思路参考+代码解析 (C++、Java、Py、C语言、JS)

题目描述 >为了达到新冠疫情精准防控的需要,为了避免全员核酸检测带来的浪费,需要精准圈定可能被感染的人群现在根据传染病流调以及大数据分析,得到了每个人之间在时间、空间上是否存在轨迹的交叉。现在给定一组确诊人品编号(X1 X2 X3.....n)在所有人当中,找出哪些人票要进行核酸检测,输出需要进行核酸检测的人数。(注意:确诊病例自身不需要再做核酸检) >  需要进行核酸检测的人,是病毒传播链条上的所有人员,即有可能通过确诊病例所能传播到的所有人   例如:A是确诊病例,A和B有接触、B和

KJ.JK 1434

Java内存溢出的几个区域,注意避坑

在开发过程中,时常会遇到内存溢出的问题,有可能是在生产环境,有的就在开发中,今天就聊一聊内存溢出。存在内存的区域:Java堆溢出虚拟机栈和本地方法栈溢出方法区和运行时常量池溢出本机内存溢出。

Java全能学习+面试指南 1287

Python-增加b站视频播放量

如果条件允许的情况下,有代理API更好,每次请求url调用API也更方便。如果没有的话,也不用担心,网上本身也有着很多免费国内代理,不过代理是否可用需要自己花点时间去检测,检测方法笔者这里就不详述了,后面有时间的话会单独针对这一块做详细说明。在开始之前,需准备代理IP。总之,在每次请求url的时候,随机带入某个IP防止被平台检测,便于达到增加播放量预期。大致思路就是针对你的目标代理平台进行IP抓取,并存入到自己本地的IP代理池。本文是该专栏的第1篇,后面会持续更新对应平台干货知识,记得关注。

Python进阶专栏《爬虫实战进阶》,《Pyppeteer从入门到精通》原创作者 5209

每天分享一个小知识——JVM之方法区和运行时常量池溢出

String str1 = new StringBuilder("计算机").append("软件").toString();监控元空间使用(如JConsole、VisualVM),警惕动态类生成框架(如Spring AOP、Groovy)。→ 按需租用的云存储(容量灵活,但需警惕无限扩张)。:字符串常量池在堆中,需限制堆大小才能触发OOM。方法区从永久代(堆内)演变为元空间(本地内存)。:移除永久代中的字符串常量池,将其移至堆内存。:同一类被不同类加载器加载,视为多个类。:永久代容量有限,直接OOM。

weixin_44343315的博客 1793

2026年03月CCF-GESP编程能力等级认证C++编程一级真题解析

本文收录于专栏《。订阅后可阅读专栏内所有文章。

人生就是一个不断学习的过程 337

Android编译系统——Android.bp语法介绍(十五)

Android.bp 是 Android 构建系统(Android Build System)中的配置文件,用于描述如何编译和打包项目中的模块。它是用 Blueprint 编写的,其语法类似于 JSON,但专为 Android 编译系统设计,提供了更高效、灵活的模块化管理。

小旭的专栏 939

java常量池方法区_Java方法区和运行时常量池溢出问题分析

运行时常量池是方法区的一部分,方法区用于存放Class的相关信息,如类名、访问修饰符、常量池、字段描述、方法描述等。String.intern()是一个native方法,它的作用是:如果字符串常量池中已经包含了一个等于此String对象的字符串,则返回代表池中这个字符串的String对象;否则,将此String对象包含的字符串添加到常量池中,并返回此String对象的引用。在JDK1.6及之前版本...

weixin_39761195的博客 242

用 ABAP 驾驭 OAuth 2.0:从 Authorization Code 到 SAML Bearer 的全栈落地指南

ABAP平台OAuth 2.0客户端开发实践 本文为SAP开发者详细解析ABAP平台内置OAuth 2.0客户端的使用方法,涵盖四种授权流的最佳实践: 授权流选择: Authorization Code:适用于用户交互场景 SAML 2.0 Bearer:适合已有SAML体系的企业 Client Credentials:系统间通信 Password Credentials:过渡方案(不推荐) 配置流程: 通过SE80定义Client Profile 使用SOAUTH2_CLIENT/OA2C_CONFIG配

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 309

Java方法区和运行时常量池内存溢出出现的原因,现象,以及解决思路

运行时常量池其实属于方法区的一部分 运行时常量池内存溢出的原因: 不断创建常量,比如字符串等。 运行时常量池内存溢出的现象: java.lang.outofmemoryerror: pergen space这也间接说明了运行时常量池其实属于方法区的一部分 方法区内存溢出的原因: 不断创建大量的类,导致类信息过多等。比如使用框架或者对代码进行修改的时候,不会对原来的类进...

逆水行舟,不进则退 1749

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

第二章:方法区和运行时常量池溢出

由于运行时常量池属于方法区的一部分,因此两个区域放在一块执行。 String.intern()是一个Native方法,它的作用是如果字符串常量池中已经包含了此String对象的字符串,则返回代表池中这个字符串的String对象;否则将此String对象包含的字符串添加到常量池中,并且返回此String对象的引用。 可以通过以下代码测试运行时常量池溢出: public class Test...

weixin_34309543的博客 157

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

Java方法区和运行时常量池溢出问题分析

运行时常量池是方法区的一部分,方法区用于存放Class的相关信息,如类名、访问修饰符、常量池、字段描述、方法描述等。   String.intern()是一个native方法,它的作用是:如果字符串常量池中已经包含了一个等于此String对象的字符串,则返回代表池中这个字符串的String对象;否则,将此String对象包含的字符串添加到常量池中,并返回此String对象的引用。在JDK1.

wangxiao870709的博客 600

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

java 常量池溢出_Java方法区和运行时常量池溢出问题分析

运行时常量池是方法区的一部分,方法区用于存放Class的相关信息,如类名、访问修饰符、常量池、字段描述、方法描述等。String.intern()是一个native方法,它的作用是:如果字符串常量池中已经包含了一个等于此String对象的字符串,则返回代表池中这个字符串的String对象;否则,将此String对象包含的字符串添加到常量池中,并返回此String对象的引用。在JDK1.6及之前版本...

weixin_32698563的博客 482

java 方法区 溢出_Java方法区和运行时常量池溢出问题分析(转)

标签:运行时常量池是方法区的一部分,方法区用于存放Class的相关信息,如类名、访问修饰符、常量池、字段描述、方法描述等。String.intern()是一个native方法,它的作用是:如果字符串常量池中已经包含了一个等于此String对象的字符串,则返回代表池中这个字符串的String对象;否则,将此String对象包含的字符串添加到常量池中,并返回此String对象的引用。在JDK1.6及之...

weixin_35541666的博客 153

OutOfMemoryError异常——方法区和运行时常量池溢出。

        由于运行时常量池是方法区的一部分,因此这两个区域的溢出测试就放在一起进行。前面提到JDK1.7开始逐步“去永久代”的事情,在此就以测试代码观察一下这件事对程序的实际影响。         String.intern()是一个Native方法,他的作用是:如果字符串常量池中已经包含一个等于此String对象的字符串,则返回代表池中这个字符串的String对象;否则,将此String...

孤芳不自赏 668

java 常量池溢出_Java方法区和运行时常量池溢出问题分析(转)

运行时常量池是方法区的一部分,方法区用于存放Class的相关信息,如类名、访问修饰符、常量池、字段描述、方法描述等。String.intern()是一个native方法,它的作用是:如果字符串常量池中已经包含了一个等于此String对象的字符串,则返回代表池中这个字符串的String对象;否则,将此String对象包含的字符串添加到常量池中,并返回此String对象的引用。在JDK1.6及之前版本...

weixin_33756596的博客 253
上一篇: 虚拟机栈和本地方法栈溢出
下一篇: 本机直接内存溢出
sells2012
博客等级 码龄15年 10粉丝 22原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值