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. python使用装饰器@函数式化django开发

    django是一个python web开发的框架.作为一个框架MVC的架构已经实现起来了.但是编码的时候你经常要进行进一步的抽象. AOP是一种称为面向切面的开发思想,意思是将部分功能代码在运行时动态 ...

  2. 【NOIP2012】提高组初赛试题(个人错题解析+相关知识点扩展)C++版

    初赛14号就要开始了,从今天到14号还有三天,已经请了两节的自习来刷题,每天三四套题,尽量把01年到16年的题目全刷一遍.[fighting!!!] 4.无论是TCP/IP模型还是OSI模型,都可以视 ...

  3. SSM框架整合项目 :租房管理系统

    使用ssm框架整合,oracle数据库 框架: Spring SpringMVC MyBatis 导包: 1, spring 2, MyBatis 3, mybatis-spring 4, fastj ...

  4. Hadoop(六)之HDFS的存储原理(运行原理)

    前言 其实说到HDFS的存储原理,无非就是读操作和写操作,那接下来我们详细的看一下HDFS是怎么实现读写操作的! 一.HDFS读取过程 1)客户端通过调用FileSystem对象的open()来读取希 ...

  5. uva10003 - Cutting Sticks(简单动规)

    /* * Author: Bingo * Created Time: 2015/2/13 18:33:03 * File Name: uva10003.cpp */ #include <iost ...

  6. 将摄像头的读入的人像放入背景视频中_with_OpenCV_in_Python

    import cv2 import numpy as np import time cap = cv2.VideoCapture(0) background_capture = cv2.VideoCa ...

  7. JVM菜鸟进阶高手之路十三(等你来战!!!)

    转载请注明原创出处,谢谢! 前几天有个朋友问了我个问题,下面给大家分享下,希望大家积极在评论区进行评论留言,等你来战!!! 先来个趣味题,热身下,引出后面的jvm题目. 地上的影子是那个人的? 地上的 ...

  8. Maven Install指令构建时出现找不到符号

    检查引用的JRE编译的版本,可能由于JRE编译版本太低导致的  

  9. MYSQL 总结

    1.数据库实质中访问的是 DBMC,数据库是一种存储介质 2.groub by 与 having 理解 group by 有一个原则,select后面的所有列中,没有使用聚合函数的列必须出现在 gro ...

  10. LeetCode 80. Remove Duplicates from Sorted Array II (从有序序列里移除重复项之二)

    Follow up for "Remove Duplicates":What if duplicates are allowed at most twice? For exampl ...