java内存

java动态运行时区域包括:方法区、虚拟机栈、本地方法栈、堆、程序计数器,如右图所示:
 
程序计数器
程序计数器用来标识要执行的代码的行号,为线程私有
 
虚拟机栈
为线程所私有
虚拟栈里存放的东西?跟线程有关?存放方法信息,包括方法名,方法参数,返回值地址等
存放局部变量表,操作数栈,动态链接,方法出口等信息
存在两种异常:
a.StackOverflowError(栈溢出异常),当方法深度大于栈深度时(如果线程请求的栈深度大于虚拟机所允许的深度)
b.OutOfMemory(内存溢出)没有更多的空间来存放线程空间
 
本地方法栈
和虚拟栈类似,区别是虚拟栈存储虚拟机方法,本地方法栈存储本地方法堆,几乎所有的对象都在堆中产生。
堆是GC的重点区域。根据对象特点可分为新生代和老年代。其中新生代又可以划分为eden,survivior1,survivor2
 
方法区
各个线程所共享,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
在HotSpot中,方法区又叫做永久代。存放一些不变的信息。类信息,常量,,,存在OOM异常
 
直接内存
OOM异常
在JDK1.4中新加入了NIO类,引入了一种基于通道与缓冲区的I/O方式,它可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在Java堆和Native中来回复制数据的开销。
 
常量池
String. intern()方法
如果常量池中存在该变量,则返回常量池中变量的指针引用。否则,把该变量添加进常量池,并返回该常量池的指针引用。
运行时常量是方法区的一部分。Class文件中除了有类的版本、字段、方法、接口等描述信息以外,还有一项信息是常量池,用于存放编译器生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中存放。
 
对象的创建

1.判断类是否加载,如果没有加载,需要加载类信息。加载完类信息以后,对象创建需要分配的内存空间是确定的。

2.为对象分配内存空间

如果可分配内存空间是连续的,则只需要在可用空间移动指针。(指针碰撞[Bump the Point])

如果可分配内存空间是不连续的,则需要维护一个剩余空间的指针列表。(空闲列表[Free List])

剩余空间是否连续与所采用的GC算法有关。例如:使用标记-清除算法(MS)剩余空间碎片不连续,使用复制算法或者标记-整理(mark-compact)算法剩余空间是连续的。

3.在堆中创建对象是很频繁的行为,所以需要确保在多线程中分配空间的安全性。有两种方式:

a.失败重试和CAS保证

b.虚拟机本地线程缓存(本地线程分配缓存[Thraed Local Allocation Buffer TLAB]),就是给每个线程分配一段内存空间,只有线程内存空间使用完或者不够新对象内存分配时才会涉及到线程之间的竞争。

4.对象初始化

分配完内存空间后,JVM会对新分配的对象进行初始化。基本数据类型被赋值为类型的初始值。

5.按照开发人员的编码初始化。

对象的访问定位

有两种方式

1.直接引用 直接指针

2.间接引用 使用句柄

 
优缺点
直接引用效率更快,间接引用在更改对象引用后不用修改指针引用。
使用直接指针最大的好处是速度快,因为它节省了一次指针定位的时间开销。
使用句柄访问的最大好处是reference中存储的是稳定的句柄地址,在对象被移动时只会改变句柄中的实例数据指针,而reference本身不需要修改。

内存溢出

堆内存溢出

产生原因:堆中没有足够多的内存完成空间分配,并且无法扩展
限制参数:-Xmx20m -Xms20m -XX:+HeapDumpOnOutOfMemoryError

实例代码:

public class HeapOoMException {
public static void main(String[] args) {
List<String> out = new ArrayList<String>();
for (int i = 0; i < 16; i++) {
out.add(_1MB._1Mb());
}
} public static String _1Mb() {
int kb = 1024;
int mb = 512 * kb;
char[] chars = new char[mb];
Arrays.fill(chars, 'f');
return new String(chars);
}
}

栈内存溢出

产生原因:线程请求栈深度大于虚拟机所允许的最大深度

限制参数:-Xss128k

实例代码:

public class StackOverFlowException {

    private static long stackLength = 0;

    public static void main(String[] args) throws Throwable {
StackOverFlowException sof = new StackOverFlowException();
try {
sof.stackLeak();
} catch (Throwable e) {
System.out.println("stack length:" + stackLength);
throw e;
}
} private void stackLeak() {
stackLength++;
stackLeak();
}
}

 方法区溢出

产生原因:由于动态代理等导致的类信息容量大于方法区容量
限制参数:-XX:PermSize=10m -XX:MaxPermSize=10m

实例代码:

public class VmMethodException {
public static void main(String[] args) {
while (true) {
Enhancer enhance = new Enhancer();
enhance.setSuperclass(OomObject.class);
enhance.setUseCache(false);
MethodInterceptor mi = new MethodInterceptor() {
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy)
throws Throwable {
return methodProxy.invoke(o, objects);
}
};
enhance.setCallback(mi);
enhance.create();
}
} static class OomObject {
}
}

jvm内存区域与内存溢出的更多相关文章

  1. JVM内存区域与内存溢出异常

    Java虚拟机在执行java程序时会把它所管理的内存会分为若干个不同的数据区域,不同的区域在内存不足时会抛出不同的异常. >>运行时数据区域的划分 (1)程序计数器程序计数器(Progra ...

  2. JVM基础知识(1)-JVM内存区域与内存溢出

    JVM基础知识(1)-JVM内存区域与内存溢出 0. 目录 什么是JVM 运行时数据区域 HotSpot虚拟机对象探秘 OutOfMemoryError异常 1. 什么是JVM 1.1. 什么是JVM ...

  3. 深入理解jvm之内存区域与内存溢出

    文章目录 1. Java内存区域与内存溢出异常 1.1. 运行时数据区域 1.1.1. 程序计数器 1.1.2. java虚拟机栈 1.1.3. 本地方法栈 1.1.4. Java堆(Java Hea ...

  4. 深入理解java虚拟机系列(一):java内存区域与内存溢出异常

    文章主要是阅读<深入理解java虚拟机:JVM高级特性与最佳实践>第二章:Java内存区域与内存溢出异常 的一些笔记以及概括. 好了開始.假设有什么错误或者遗漏,欢迎指出. 一.概述 先上 ...

  5. 深入理解JVM之JVM内存区域与内存分配

    深入理解JVM之JVM内存区域与内存分配 在学习jvm的内存分配的时候,看到的这篇博客,该博客对jvm的内存分配总结的很好,同时也利用jvm的内存模型解释了java程序中有关参数传递的问题. 博客出处 ...

  6. 深入理解java虚拟机---->java内存区域与内存溢出异常

    2. java内存区域于内存溢出异常 2.1 概述: 对于C/C++而言,内存管理具有最高的权利,既拥有每一个对象的“所有权”,又担负着每一个对象生命开始到结束的维护责任. 对于java而言,则把内存 ...

  7. 第二章Java内存区域与内存溢出异常

    第二章 Java内存区域与内存溢出异常 一.概述 对与Java程序员来说,在虚拟机自动内存管理机制的帮助下,不再需要为每个new操作去写delete/free代码,不容易出现内存泄露和内存溢出问 题, ...

  8. 《深入理解java虚拟机》第二章 Java内存区域与内存溢出异常

    第二章 Java内存区域与内存溢出异常 2.2 运行时数据区域  

  9. 深入了解Java虚拟机(1)java内存区域与内存溢出异常

    java内存区域与内存溢出异常 一.运行时数据区域 1.程序计数器:线程私有,用于存储当前所执行的指令位置 2.Java虚拟机栈:线程私有,描叙Java方法执行模型:执行方法时都会创建一个栈帧,存储局 ...

  10. 2.1 自动内存管理机制--Java内存区域与内存溢出异常

    自动内存管理机制 第二章.Java内存区域与内存溢出异常 [虚拟机中内存如何划分,以及哪部分区域.什么样代码和操作会导致内存溢出.各区域内存溢出的原因] 一.运行时数据区域 Java虚拟机所管理的内存 ...

随机推荐

  1. SAP 参照sto订单创建外向交货BAPI

    DATA: SHIP_POINT TYPE TVST-VSTEL, "装运点/接收点 NUM_DELIVERIES TYPE VBNUM, STOCK_TRANS_ITEMS WITH HE ...

  2. ABAP 内表数据 与 Json串 相互转换

    内表: A B C IMINGZHA  HAIMINGZ AIMINGZH 1 2 3 4 5 6 Json串:  [{a: "IMINGZHA", b: "HAIMIN ...

  3. WPF checkbox文字下掉

    WPF checkbox文字下掉 可以使用 <Style TargetType="CheckBox"> <Setter Property="Margin ...

  4. LINUX 笔记-ls命令

    常用参数: -l :列出长数据串,包含文件的属性与权限数据等 -a :列出全部的文件,连同隐藏文件(开头为.的文件)一起列出来(常用) -d :仅列出目录本身,而不是列出目录的文件数据 -h :将文件 ...

  5. Python学习笔记(二)-Python文件类型及编程模式

    Python环境搭建:linux,Windows... Linux下:[root@localhost StudyPython]# python #进入交互模式Python 2.7.11 (defaul ...

  6. Linux下Crontab定时任务的使用教程 以及 无法执行定时任务的解决方案

     前言 本文学习思路:Linux的corntab定时任务的使用教程  --> 定时任务无效的解决方案  Linux的corntab定时任务的使用教程 1. 首先,输入命令 打开crontab定时 ...

  7. PHP的重载及魔术方法

    首先你要知道什么是php的魔术方法,它不是变魔术的,如果你想学习变魔术来错地方了哦! 定义:PHP 将所有以 __(两个下划线)开头的类方法保留为魔术方法.所以在定义类方法时,除了上述魔术方法,建议不 ...

  8. 【Salvation】——登录注册存储数据&验证用户

    写在前面:登录注册功能是在纯Unity3D环境内实现的,用到UGUI绘制界面技术,数据库的部分是后面拓展加进来的,这里数据存储是指存在XML用户文件中. 注册用户名和密码 zc() 用户名和密码登录 ...

  9. 径向基网络(RBF network)

    来源:http://blog.csdn.net/zouxy09/article/details/13297881 1.径向基函数 径向基函数(Radical Basis Function,RBF)方法 ...

  10. KMP (next数组的性质及证明)

    性质:如果len%(len-next[len-1])==0,则字符串中必存在最小循环节,且循环次数即为len/(len-next[len-1]); 证明:在前len个字符组成的字符串,存在最小循环节k ...