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

《深入理解Java虚拟机》读后总结(二)JVM内存分配

    博客分类:
  • JVM
阅读更多

《深入理解Java虚拟机》读后总结

(一)Sun HotSpot JVM内存模型

(二)Sun HotSpot JVM内存分配

(三)Sun HotSpot JVM内存监控

(四)Sun HotSpot JVM垃圾回收

 

基于Sun HotSpot JVM 

请先了解JVM内存模型在来看此篇文章

使用对JVM不同内存区域灌入数据,导致相关区域内存溢出,来验证JVM内存分配

 

先看一个经典问题:

String s1 = "小金子(aub)";
String s2 = "小金子(aub)";
String s3 = "小金子" + "(aub)";
String s4 = new String("小金子(aub)");
String s5 = "小金子" + new String("(aub)");
String s6 = s4.intern();
System.out.println("s1 == s2: " + (s1 == s2));//true;
System.out.println("s1 == s3: " + (s1 == s3));//true;
System.out.println("s2 == s3: " + (s2 == s3));//true;
System.out.println("s1 == s4: " + (s1 == s4));//false;
System.out.println("s1 == s5: " + (s1 == s5));//false;
System.out.println("s4 == s5: " + (s4 == s5));//false;
System.out.println("s1 == s6: " + (s1 == s6));//true;

 原因就在与String对象特殊的内存分配方式:(Strings pool是JVM内存中运行时常量池的一部分)

1.String s1 = new String("小金子(aub)");

2.String s2 = "小金子(aub)";
3.String s3 = "小金子" + "(aub)";

  虽然两个语句都是返回一个String对象的引用,但是jvm对两者的处理方式是不一样的。

对于第一种,jvm会马上在heap中创建一个String对象,然后将该对象的引用返回给用户。

对于第二种,jvm首先会在内部维护的strings pool中通过String的 equels 方法查找是对象池中是否存放有该String对象,如果有,则返回已有的String对象给用户,而不会在heap中重新创建一个新的String对象;如果对象池中没有该String对象,jvm则在heap中创建新的String对象,将其引用返回给用户,同时将该引用添加至strings pool中。

注意:使用第一种方法创建对象时,jvm是不会主动把该对象放到strings pool里面的,除非程序调用 String的intern方法

对于第三种,jvm会进行“+”运算符号的优化,两遍都是字符串常量会做类似于第二种的处理,如果“+”任意一边是一个变量,就会做类似第一种的处理。

 

JVM栈和Native Method栈内存分配:

JAVA中八个基本类型数据,在运行时都是分配在栈中的。在栈上分配的内存,随着数据的进栈出栈,方法运行完毕,或则线程结束时,自动被回收掉了。

测试代码如下:

public class JvmStackOOM {
	private int stackLength = 1;

	public void execute() {
		try {
			stackLeak();
		} catch (Throwable e) {
			System.out.println("stackLength : " + stackLength);
			e.printStackTrace();
		}
	}

	private void stackLeak() {
		stackLength++;
		stackLeak();
	}
}

用一个递归不断地对实例变量stackLength进行自增操作,当JVM在扩展栈时无法申请到足够的空间,将产生StackOverflowError

可以使用Jvm 参数-Xss配置栈大小,例如:-Xss2M,栈内存越大,可的栈深度越大,在内存不变的情况下,jvm可创建的线程就越少,需要合理设置。

 

方法区内存分配:

 类信息和运行时常量将会分配到此区域。

测试代码如下:

public class JvmRuntimeConstantPoolOOM {
	private int runtimeConstantCount = 1;

	public void execute() {
		try {
			runtimeConstantLeak();
		} catch (Throwable e) {
			System.out.println("runtimeConstantCount : " + runtimeConstantCount);
			e.printStackTrace();
		}
	}

	private void runtimeConstantLeak() {
		List<String> list = new ArrayList<String>();
		while (true) {
			list.add(String.valueOf(runtimeConstantCount++).intern());
		}
	}
}

使用String的intern()方法向方法区中灌入数据,当方法区内存不足时,抛出OutOfMemoryError: PermGen space,

也可以加载过多的类的方式,测试是否有OutOfMemoryError: PermGen space异常,如果有说明类信息也是存放在方法区中的可以

使用Jvm 参数-XX:PermSize和-XX:MaxPermSize配置栈大小,例如:-XX:PermSize=10M -XX:MaxPermSize=10M

 

堆内存分配:

所有对象实例及数组都会在堆上分配。

堆分为新生代和老年代。新生代分为3个区域:一个eden区,和两个survivor区(互为From、To,相对的),

新建对象时首先想eden区申请分配空间,如果空间够,就直接进行分配,否则进行一次Minor GC(新生代垃圾回收)

Minor GC后再次尝试将对象放到eden区,如果空间仍然不够,直接在老年代创建对象。

测试代码如下:

public class JvmHeapOOM {
	private int bojectCount = 1;

	public void execute() {
		try {
			heapLeak();
		} catch (Throwable e) {
			System.out.println("bojectCount : " + bojectCount);
			e.printStackTrace();
		}
	}

	private void heapLeak() {
		List<OOMObject> list = new ArrayList<OOMObject>();
		while (true) {
			list.add(new OOMObject());
			bojectCount++;
		}
	}

	private class OOMObject {
		
	}
}

创建多个OOMObject对象放到List中,当堆内存不足时,产生OutOfMemoryError:Java Heap space

使用Jvm 参数-Xm -Xmx -Xmn -XX:SurvivorRatio配置堆,例如:-Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8

 

本地直接内存分配: 

堆外内存,NIO相关操作将在此分配内存

使用Jvm 参数-XX:MaxDirectMemorySize配置,例如:-XX:MaxDirectMemorySize=10M

 

所有用到的JVM启动参数:
-Xss2M       设置JVM栈内存大小
-Xms20M    设置堆内存初始值
-Xmx20M    设置堆内存最大值
-Xmn10M    设置堆内存中新生代大小
-XX:SurvivorRatio=8  设置堆内存中新生代Eden 和 Survivor 比例
-XX:PermSize=10M  设置方法区内存初始值
-XX:MaxPermSize=10M  设置方法区内存最大值
-XX:MaxDirectMemorySize=10M 设置堆内存中新生代大小 

 

原创文章,转载请指明出处:http://aub.iteye.com/blog/1872936

10
9
分享到:
评论
4 楼 occhio 2013-05-26  
牛叉叉……
3 楼 wpf523 2013-05-22  
     
2 楼 aubdiy 2013-05-22  
xusheng87 写道
  ❤哥 顶起。

感谢鼓励
1 楼 xusheng87 2013-05-22  
  ❤哥 顶起。

相关推荐

    30+个视频+深入理解Java虚拟机(jvm优化+内存模型+虚拟机原理)

    根据提供的文件标题、描述、标签以及部分内容,我们可以深入探讨与Java虚拟机(JVM)相关的多个核心知识点。以下是对这些主题的详细阐述: ### Java虚拟机(JVM)概述 Java虚拟机(JVM)是一种用于执行Java字节码的...

    深入理解java虚拟机视频教程

    深入理解java虚拟机视频教程,jvm原理,java虚拟机,jvm性能调优,内存模型,gc工作原理,内存分配,类的加载等等视频教程

    java-jvm虚拟机原理.ppt

    Java虚拟机(JVM)是Java程序运行的核心组件,它为Java代码提供了平台无关的运行环境。本篇文章将深入探讨JVM的生命周期、体系结构、类加载机制、内存区域以及垃圾收集。 首先,JVM的生命周期与Java程序紧密关联。...

    深入java虚拟机 高清pdf 高清高清高清

    《深入Java虚拟机》这本书是Java开发者深入了解JVM(Java Virtual Machine)的必备经典之作。它详尽地探讨了Java虚拟机的工作原理、内存管理、类加载机制、字节码执行以及性能优化等多个核心主题,旨在帮助开发者...

    深入JAVA虚拟机 不那么完美的第二版.pdf.zip

    虽然《深入JAVA虚拟机》的第二版可能在物理形态上有些许不足,但其内容依然对理解JVM的运作机制有着重要的指导意义。学习这些知识点,有助于Java开发者提升代码的运行效率,解决内存问题,以及进行性能优化。

    深入JAVA虚拟机第二版 Bill Venners著 曹晓钢 蒋靖译

    这本书是Java开发者必备的经典读物,它详细地解析了Java虚拟机(JVM)的工作原理,帮助读者深入理解Java程序的运行机制。尽管描述中提到内容为图片形式,但我们可以从其主题和标签中提炼出许多关于JVM的重要知识点。...

    深入理解Java 虚拟机内存模型.rar

    Java虚拟机(JVM)内存模型是Java...总的来说,深入理解Java虚拟机内存模型有助于我们更好地设计和优化Java应用程序,避免因内存问题导致的性能瓶颈或系统崩溃。通过学习和实践,我们可以编写出更高效、更稳定的代码。

    深入理解Java虚拟机学习笔记借鉴.pdf

    Java 虚拟机(JVM)自动内存管理机制 Java 虚拟机(JVM)自动内存管理机制是 Java 语言的一大特色,它使得 Java 程序员无需手动管理内存,从而提高了开发效率和程序稳定性。JVM 自动内存管理机制主要通过 JVM 的...

    JAVA虚拟机(JVM)规范(中文版).rar

    **JAVA虚拟机(JVM)规范** JAVA虚拟机(JVM)是Java语言的核心组成部分,它为Java程序提供了运行环境,使得Java代码能在任何支持JVM的平台上运行,实现了“一次编写,到处运行”的目标。JVM规范定义了Java程序如何...

    深入JAVA虚拟机第二版.7z

    《深入JAVA虚拟机第二版》是一...总结,《深入JAVA虚拟机第二版》深入剖析了JVM的各个方面,不仅涵盖了基础理论,还提供了实用的调优技巧。通过学习本书,开发者可以更好地理解Java运行机制,提升代码质量和系统性能。

    学习深入理解Java虚拟机的前几章笔记

    ### 学习深入理解Java虚拟机的前几章笔记 #### JVM内存模型 Java虚拟机(JVM)的内存模型主要分为两大类:线程共享区和线程私有区。 ##### 线程共享区 - **堆**:是所有线程共享的内存区域,在这里存放着对象实例...

    深入理解Java虚拟机视频教程(jvm性能调优+内存模型+虚拟机原理)视频教程

    第31节深入理解对象的访问定位00:08:01分钟 | 第32节垃圾回收-概述00:06:20分钟 | 第33节垃圾回收-判断对象是否存活算法-引用计数法详解00:14:08分钟 | 第34节垃圾回收-判断对象是否存活算法-可达性分析法详解00:...

    java 虚拟机参数配置说明及Myeclipse内存不足

    在IT行业中,Java虚拟机(JVM)是Java程序运行的核心,它负责解析并执行Java字节码。本文将深入探讨Java虚拟机的参数配置,特别是针对MyEclipse开发环境中遇到的内存不足问题。 首先,Java虚拟机参数配置是优化JVM...

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

    本资料总结主要关注JVM内存分配及其运行原理,这对于理解和优化Java应用程序的性能至关重要。 1. **JVM内存结构** JVM内存分为几个关键区域:方法区(Method Area)、堆(Heap)、栈(Stack)、程序计数器(PC ...

    java -jvm 内存分配和jvm调优

    总结,Java JVM内存分配和调优是一项复杂的任务,需要结合实际应用的需求和性能指标来调整。通过理解JVM内存模型,选择合适的垃圾收集器和设置合理的内存参数,可以有效提升Java应用的性能和稳定性。在实践中,不断...

    深入Java虚拟机 JVM pdf

    《深入Java虚拟机》是Java开发者必读的经典之作,它详细阐述了Java虚拟机(JVM)的工作原理和内部机制,对于理解Java程序的运行方式、优化代码性能以及排查问题具有极其重要的价值。这本书的第二版更是加入了更多...

    深入理解Java虚拟机1

    深入理解Java虚拟机,首先要明白Java虚拟机(JVM)的角色和功能。JVM是Java平台的核心组成部分,它负责执行Java程序,提供了一个跨平台的运行环境。在Java的发展历程中,Classic VM作为世界上第一款商用的Java虚拟机...

Global site tag (gtag.js) - Google Analytics