OutOfMemoryError异常系列之方法区溢出和运行时常量溢出池溢出

按照虚拟机的内存分配,运行时常量池属于方法区,所以今天在这一起讲了,大家都知道1.7的虚拟机规范出来以后,有个很重要的一点就是去永久代。今天我们就来观察一下这个实际影响。

String.intern()是一个Native方法。作用就是如果常量池中有这个String变量,则取出,没有的话就是放进去。并返回其String的引用。

在此我们可以看一下1.6的版本使用一个死循环while(true),不断的将String.valueOf(i++).intern()放入一个list中(i之所以变化,是为了不放入同一个String,不然他就会不断地取旧值,不会溢出),为了尽快见到结果,我们可以设置常量池容量,设置-XX:PermSize和-XX:MaxPermSize即可。最后系统会报OutOfMemoryError:PermGen space错误,(我电脑是1.8的jdk,不想下载 了,所以1.6的只是给大家说说,不写代码了)。从这个运行结果可以看出,运行时常量溢出,后面的这个PerGen space说明运行时常量是方法区的一部分。如果大家使用jdk1.7以上版本。将不会报错,while将一直循环下去

/** * VM args : -XX:PermSize=10M -XX:MaxPerSize=10M * Created by 刘洋 on 2017/9/26 0026. */public class RuntimeConstantPool {    public static void main(String [] args){        List<String> list = new ArrayList<>();        int i = 1;        while (true){            list.add(String.valueOf(i++).intern());            System.out.println(i);        }    }}

实验证实,大家可以自己试试。其实还有一个影响,下面贴代码:

public static void main(String [] args){    String str1 = new StringBuilder("123").append("456").toString();    System.out.print(str1.intern() == str1);    String str2 = new StringBuilder("789").append("0").toString();    System.out.print(str2.intern() == str2);}

这个运行在1.7结果是true false,但是在1.6是false false

至于为什么,大家可以自行理解,今天有点累写不动了,下一篇文章我会给大家详解并说一下方法区异常。

原文发布于微信公众号 - 精讲JAVA(toooooooozi)

原文发表时间:2017-09-26

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏java一日一条

Java反射在JVM的实现

反射使程序代码能够接入装载到JVM中的类的内部信息,允许在编写与执行时,而不是源代码中选定的类协作的代码,是以开发效率换运行效率的一种手段。这使反射成为构建灵活...

2153
来自专栏IT可乐

Spring详解(三)------DI依赖注入

  上一篇博客我们主要讲解了IOC控制反转,也就是说IOC 让程序员不在关注怎么去创建对象,而是关注与对象创建之后的操作,把对象的创建、初始化、销毁等工作交给s...

2005
来自专栏前端侠2.0

co yield避免嵌套详细代码示例。

1471
来自专栏ShaoYL

iOS 声明属性关键字讲解

35917
来自专栏xingoo, 一个梦想做发明家的程序员

堆 栈-相关知识

一、预备知识—程序的内存分配 一个由c/C++编译的程序占用的内存分为以下几个部分 1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量...

1968
来自专栏ImportSource

JVM中的“同步”到底是怎么实现的?

JVM中的Synchronization是使用monitor entry和exit来实现的。不管是显式的还是隐式的。显式的是通过使用monitorenter和m...

2885
来自专栏向治洪

java虚拟机构造原理

 Java虚拟机的生命周期 一个运行中的Java虚拟机有着一个清晰的任务:执行Java程序。程序开始执行时他才运行,程序结束时他就停止。你在同一台机器上运行三...

2046
来自专栏测试开发架构之路

堆和栈的区别

一、预备知识—程序的内存分配          一个由C/C++编译的程序占用的内存分为以下几个部分     1、栈区(stack)— 由编译器自动分配释放,存...

2878
来自专栏你不就像风一样

深入理解Java虚拟机(类文件结构+类加载机制+字节码执行引擎)

周志明的《深入理解Java虚拟机》很好很强大,阅读起来颇有点费劲,尤其是当你跟随作者的思路一直探究下去,开始会让你弄不清方向,难免有些你说的啥子的感觉。但知识不...

1292
来自专栏Java编程技术

什么是重排序与中断

Java内存模型中,允许编译器和处理器对指令进行重排序,但是重排序可以保证最终执行的结果是与程序顺序执行的结果一致,并且只会对不存在数据依赖性的指令进行重排序,...

822

扫码关注云+社区

领取腾讯云代金券