`
iluoxuan
  • 浏览: 579207 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

JVM内存管理以及内存溢出情况

    博客分类:
  • jvm
 
阅读更多

首先我们要了解JVM内存划分,以及每个部分的功能

 



 

   JVM内存管理大概来说分为 堆 和栈 两个部分

    堆上是所有线程共享的数据区,而栈上数据是私有的

 

    上图是JAVA运行时虚拟机时的数据区

    

     方法区: 保存类的class信息,类描述,类的方法描述等,其中还有一部分就是 运行时的常理池

                    运行时的常理池

/**
 * java中基本类型的包装类的大部分都实现了常量池技术,这些类是Byte,Short,Integer,Long,Character,Boolean,
 * 另外两种浮点数类型的包装类则没有实现。
 * 另外Byte,Short,Integer,Long,Character这5种整型的包装类也只是在对应值小于等于127时才可使用对象池,
 * 也即对象不负责创建和管理大于127的这些类的对象。以下是一些对应的测试代码:
 *  
     String 也是实现了常理池的  intern()方法参考
 * @author 
 * @version 1.0
 * @since 1.0
 */
public class Test {

	public static void main(String[] args) {
		//5种整形的包装类Byte,Short,Integer,Long,Character的对象,
		//在值小于127时可以使用常量池
		Integer i1 = 127;
		Integer i2 = 127;
		System.out.println(i1 == i2);//输出true
		//值大于127时,不会从常量池中取对象
		Integer i3 = 128;
		Integer i4 = 128;
		System.out.println(i3 == i4);//输出false
		//Boolean类也实现了常量池技术
		Boolean bool1 = true;
		Boolean bool2 = true;
		System.out.println(bool1 == bool2);//输出true
		//浮点类型的包装类没有实现常量池技术
		Double d1 = 1.0;
		Double d2 = 1.0;
		System.out.println(d1 == d2);//输出false

	}
}

   

    引用《深入理解java虚拟机》

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

由于运行时常量池是方法区的一部分,因此这两个区域的溢出测试就放在一起进行。前面提到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直接操作字节码运行时生成了大量的动态类。  

 

    堆上方的对象实例和数组

 

     

  • 大小: 247.2 KB
分享到:
评论

相关推荐

    JVM内存溢出问题解析

    JVM 内存溢出是指程序运行所需的内存大于虚拟机能提供的最大内存的情况。这种情况可能是由于数据量过大、死循环、静态变量和静态方法过多、递归、无法确定是否被引用的对象等原因引起的。同时,虚拟机不回收内存...

    jvm内存溢出

    了解JVM内存结构是理解内存溢出的关键。 #### 二、JVM运行时数据区域 - **程序计数器(Program Counter Register)**:当前线程所执行的字节码的行号指示器。每条线程拥有独立的程序计数器,因此它属于线程私有区域...

    jvm内存管理,pdf

    ### JVM内存管理详解 #### 一、引言 在探讨JVM内存管理之前,我们先来看一下为何要深入了解这一主题。对于深入掌握Java的人来说,内存管理是不可或缺的一部分。随着技术的发展,内存管理变得越来越自动化,但这也...

    JVM原理及内存溢出经典案列分析.ppt

    简单的判断JVM内存溢出的方法

    jvm 内存分析文档

    JVM内存管理主要包括内存结构、内存分配以及垃圾回收(GC)等方面。了解这些知识对于优化Java应用程序的性能至关重要。 ### 1. JVM内存结构 #### 1.1.1 JVM内存概述 JVM内存分为几个关键区域,每个区域都有特定的...

    JVM内存管理及调优

    JVM内存管理是优化Java应用性能的关键环节,涉及到内存分配、垃圾回收以及内存溢出等问题。毕玄,一位在淘宝有着丰富经验的专家,通过他的演讲PPT,我们能深入理解JVM内存的实现、使用和调优。 ### 一、JVM内存实现...

    Sun JVM原理与内存管理

    - **Soft**:软引用,当系统即将发生内存溢出时会被回收。 - **Weak**:弱引用,在下一次GC时就会被回收。 - **Phantom**:虚引用,仅用于跟踪对象被垃圾回收的时间点。 #### 六、分代管理 - **Sun Hotspot 对 ...

    JVM内存模型

    在实际应用中,需要根据具体情况选择合适的优化方法,避免内存溢出异常的发生。同时,需要注意JVM所占的内存总量是堆内存、永久区内存和所有线程所占的栈内存总和。 JVM内存模型是Java虚拟机(JVM)中的一种内存...

    JVM内存模型以及垃圾回收相关资料

    垃圾回收机制是为了有效地管理内存,防止内存泄漏和内存溢出。在新生代,垃圾回收通常采用复制算法,将Eden区存活的对象复制到Survivor区,当Survivor区满时,再将存活对象移到老年代。老年代则使用标记-压缩算法,...

    java获得jvm内存大小

    了解并监控JVM的内存使用情况,对于预防和解决内存溢出错误至关重要。通过动态地调整`-Xms`和`-Xmx`参数,可以在运行时根据实际需求优化内存分配,从而提高程序的性能和稳定性。此外,定期检查和分析`heapSize`、`...

    JVM内存配置优化

    ### JVM内存配置优化 #### 一、理解JVM内存模型 在进行JVM内存配置优化之前,我们需要...以上就是关于JVM内存配置优化以及Tomcat并发配置优化的相关知识点。通过合理的配置调整,可以有效提升系统的稳定性和性能。

    深入理解JVM内存区域与内存溢出异常

    深入理解JVM内存区域与内存溢出异常

    内存溢出配置,内存溢出配置

    内存溢出配置是IT行业中,尤其是在Java应用开发与运维领域中的一个重要话题,它涉及到系统资源管理、性能调优以及故障排查等多个方面。标题与描述中重复提到“内存溢出配置”,这表明了对这一主题的关注与重视。接...

    关于JVM内存溢出的原因分析及解决方案探讨.docx

    本文主要讨论了 JVM 中的内存溢出问题,包括内存溢出的定义、内存泄漏和内存溢出的区别与联系、JVM 垃圾回收机制、内存溢出的原因分析、常见的四种内存溢出情况以及解决方案。 一、内存溢出的定义 内存溢出是指...

    JVM 内存结构及配置总结

    在Java 8以前,这部分也被称为永久代(Permanent Generation),在Java 8中被元空间(Metaspace)取代,以避免内存溢出问题。 - **堆(Heap)**:这是JVM中最大的一块内存,用于存储对象实例和数组。堆被划分为...

    在Eclipse状态栏上增加JVM内存用量指示器

    标题 "在Eclipse状态栏上增加JVM内存用量指示器" 涉及到的是一个关于Eclipse集成开发环境(IDE)的自定义配置和优化技术。Eclipse是一款广泛使用...这个过程需要对Eclipse的插件系统、JVM内存管理和配置有一定的了解。

    关于tomcat乱码以及tomcat jvm 内存溢出问题的解决方案和理论

    标题中的“关于tomcat乱码以及tomcat jvm 内存溢出问题的解决方案和理论”涉及了两个关键的IT概念:Tomcat服务器的字符编码问题和Java虚拟机(JVM)内存管理的问题。让我们逐一深入探讨这两个主题。 首先,我们来...

    java中jvm内存分配相关资料总结整理

    4. **内存溢出问题** - **栈溢出**:如果栈帧过大或者线程太多,可能导致栈空间不足,出现StackOverflowError。 - **堆溢出**:如果创建太多对象或对象占用内存过大,堆内存可能会耗尽,抛出OutOfMemoryError。 5...

    如何避免JDBC引起的内存溢出情况

    本文将重点讨论如何在MySQL、SQL Server以及Oracle三种不同的数据库环境下,通过合理配置和优化策略来避免内存溢出。 #### 一、理解内存溢出的原因 内存溢出通常发生在应用程序消耗了超出虚拟机所能分配的最大堆...

Global site tag (gtag.js) - Google Analytics