一、JVM截图及概念

图1:JVM虚拟机运行时数据区域概念模型

1、程序计数器:内存空间中的一块小区域,作为当前线程所执行的字节码的行号指示器,注:如果是native方法,计数器为空

2、虚拟机栈:线程私有,生命周期与线程相同,虚拟机栈描述的是Java方法执行的内存模型:创建栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息

3、本地方法栈:和虚拟机栈功能类似,虚拟机使用本地Native方法服务

4、Java堆:线程共享,用于存放对象,是GC的主要管理区域

5、方法区:线程共享,用于存储已被虚拟机加载的类信息,变量,静态变量,即时编译器编译后的代码等数据

6、运行时常量池:编译期生成的各种字面量和符号引用

7、直接内存:直接内存不属于虚拟机运行时数据区的一部分,但是这部分内存也会被频繁的使用,而且也会导致OutOfMemoryError的异常

在JDK1.4中引入的NIO类中,有一种基于通道和缓存区的I/O方式,可以使用native函数直接调用堆外内存,然后使用Java堆中的DirectByteBuffer对象来引用操作,可以提高JVM的性能

二、JVM中对象的创建

当JVM解析,遇到new指令时,JVM首先去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个类是否被加载、解析和初始化过。

如果没有,那必须先执行相应的类加载过程(加载,验证,准备,解析,初始化),在类加载检查通过后,JVM会对新生对象在Java堆中分配内存,内存的大小在类加载完成后才能够完全确定。Java内存的分配方式有:指针碰撞和空闲列表,他们的分配原则是根据JVM中堆是否规整决定的。

对象在内存中的布局可以分为3块区域:对象头(运行时数据【哈希码,GC分代年龄,锁状态标志,线程持有的锁,偏向线程ID,偏向时间戳】,类型指针【指向类元数据指针】)、实例数据和填充

三、JVM中对象的访问

在JVM中对象的访问主要使用:句柄和指针

图2:使用句柄访问对象

图3:使用指针访问对象

两种对象访问方式各有优势,使用句柄来访问的最大好处是reference中存储的是稳定的句柄地址,在对象被移动时只会改变句柄中的实例数据指针,而reference本身不需要修改。使用直接指针访问方式的最大好处就是速度更快,它节省了一次指针定位的时间开销。HotSpot虚拟机使用的是直接指针访问的方式。句柄来访问的情况也十分常见。

四、Java中出现OutOfMemoryError的情况

在图1的JVM虚拟机运行时数据区域概念模型中存在程序计数器、虚拟机栈、本地方法栈、Java堆、方法区、运行时常量池、直接内存,除了程序计数器,其他的部分如果操作不当都会产生运行时内存溢出的问题,下面将对虚拟机栈、本地方法栈、Java堆、方法区、运行时常量池、直接内存的溢出情况作阐述:

1、Java堆溢出

一般创建的对象在堆中容纳不下就会溢出,当抛出内存溢出问题时,需要进一步确定到底是内存泄露还是内存溢出,如果是内存泄露,那么进一步通过工具查看泄露对象到GC Roots的引用链,找到泄露代码的位置;如果是内存溢出,那么可以在物体机器中调大堆参数(-Xmx和-Xms),也需要检查代码中是否存在某些对象生命期过长、持有状态时间过程的情况,尝试减少程序运行期的内存消耗

2、虚拟机栈和本地方法栈溢出

虚拟机栈和本地方法栈溢出原因可能有以下两种:StackOverflowError异常和OutOfMemory异常

注:在单线程条件下,无论是请求的栈深度大于虚拟机所允许的最大深度,还是内存溢出,虚拟机都会抛出StackOverflowError异常,多线程会出现内存溢出异常

故:在多线程导致内存溢出,在不能减少线程数量和更换虚拟机的情况下,只能通过减少最大堆和减少栈容量来换取更多的线程

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

方法区用于存放Class的相关信息,如类名、访问修饰符、常量池、字段描述、方法描述,所以在产生大量动态类时,方法区就会出现溢出。例如CGLib字节码增强和动态语言以外,还有大量JSP或者动态产生JSP文件的应用和基于OSGI的应用

4、直接内存溢出:略

JVM模型及内存溢出的更多相关文章

  1. JVM原理及内存溢出

    JVM原理及内存溢出

  2. 【深入Java虚拟机】之一:Java内存模型与内存溢出

    [深入Java虚拟机]之:Java内存区域与内存溢出 高速缓存模型如下: ----------------------------------------------------分割线-------- ...

  3. jvm中的内存溢出与内存泄露

    内存溢出: 就是我们通常遇到的OutOfMemoryError异常,它俗理解就是内存不够,通常在运行大型程序时发生,当程序所需要的内存远远超出了JVM内存所承受大小,就会报出OutOfMemoryEr ...

  4. JVM探秘:内存溢出

    本系列笔记主要基于<深入理解Java虚拟机:JVM高级特性与最佳实践 第2版>,是这本书的读书笔记. 在 Java 虚拟机内存区域中,除了程序计数器外,其他几个内存区域都可能会发生OutO ...

  5. JVM(2) Java内存溢出异常

    在Java虚拟机运行时数据区中,除了程序计数器之外,虚拟机栈.本地方法栈.方法区和Java堆都有发生OutOfMemoryError(简称OOM)异常的可能. 一.Java堆溢出 Java堆用于存储对 ...

  6. JVM 中发生内存溢出的 8 种原因及解决办法

    1. Java 堆空间 2. GC 开销超过限制 3. 请求的数组大小超过虚拟机限制 4. Perm gen 空间 5. Metaspace 6. 无法新建本机线程 7. 杀死进程或子进程 8. 发生 ...

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

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

  8. JVM探秘2--详解内存溢出OutOfMemoryError异常

    JVM运行时内存被划分成多个区域,而除了程序计数器之外,其他几个区都会出现OutOfMemoryError异常,主要原因就是对应内存区域的内存不足以再分配内存,一般要么是内存泄漏了要么就是内存参数设置 ...

  9. BAT面试必问题系列:深入详解JVM 内存区域及内存溢出分析

    前言 在JVM的管控下,Java程序员不再需要管理内存的分配与释放,这和在C和C++的世界是完全不一样的.所以,在JVM的帮助下,Java程序员很少会关注内存泄露和内存溢出的问题.但是,一旦JVM发生 ...

随机推荐

  1. lamp :在Linux 下搭建apache、Mysql、php

    CentOS下搭建LAMP环境 LAMP: Linux + Apache + PHP + Mysql. 系统: CentOS 7,64位. CentOS安装 我选取了64位的CentOS 7这个Lin ...

  2. nexus 绑定负载均衡nginx反向代理后 遇到的https问题。

    1.今天搭建maven私服,下载安装好nexus运行后,通过IP可以直接访问,没有问题,如:http://123.123.123.123:8081 就可以进入主页面.没有任何问题. 2.但是他默认是h ...

  3. IEnumerable<T>和IQuryable<T>的区别

    https://stackoverflow.com/questions/1578778/using-iqueryable-with-linq/1578809#1578809 The main diff ...

  4. arcgis js 之 渔网工具(调用地图服务)

    arcgis js 之 渔网工具(调用地图服务) 原理: 简历不同级别的网渔网图层,设置显示比例尺.然后发布服务,使用MapImageLayer接收. 过程: 1.在arcmap中用创建渔网工具将不同 ...

  5. JavaScript 的编译原理

    JavaScript 是一门编译语言. JavaScript 的编译是发生在代码执行前的几微米(甚至更短)的事件内,所以 JavaScript 没有其他语言那么多的时间来进行优化. 当 JavaScr ...

  6. web开发中的Cookie与Session技术

    Cookie Cookie的由来 HTTP协议是无状态的,无状态的意思是每次请求都是独立的,它的执行情况和结果与前面的请求和之后的请求都无直接关系,它不会受前面的请求响应情况直接影响,也不会直接影响后 ...

  7. boost交叉编译

    运行bootstrap.sh # ./bootstrap.sh 生成b2.bjam和project-config.jam文件 修改project-config.jam using gcc : arm ...

  8. SpringBoot+MyBatis+Mysql 6.X 版本日期型数据获,时间错乱,jason序列化时间相差8小时问题

    新项目是用的springboot+mybatis+mysql 6.0.6版本的驱动包来搭建的,在使用的过程中遇到以下2个问题 从mysql取的的数据日期时间,与真实的时间往后错乱了14个小时. spr ...

  9. jQuery EasyUI 应用 – 创建 CRUD 应用(表格)

    jQuery EasyUI 应用 - 创建 CRUD 应用 本节介绍如何创建CRUD应用. CRUD分别是指在做计算处理时的增加(Create).读取查询(Retrieve).更新(Update)和删 ...

  10. 将windows当做linux/Mac来用 scoop强大的包管理工具

    在Linux中有apt-get.yum这些包安装管理 安装相当方便:如ubuntu安装一个mysql5.7,只需要一个简单的命令: apt-get 而在windows中需要在MySQL官网下载对应版本 ...