内存划分:

java虚拟机在执行java程序过程中会把内存分为以下区域进行管理

线程私有的
  虚拟机栈
    局部变量表
      基本数据类型
        long和double占用两个slot
      对象引用
      返回地址

    操作数栈
    动态链接
    方法出口等信息

    抛出异常:

      栈深度过大 StackOverflowError
      申请内存空间不足 OutOfMemoryError

  程序计数器

  本地方法栈
线程共享的
  堆
    虚拟机启东时创建
  方法区
    常量池的回收和类型的卸载
    运行常量池:字面量和符号引用 翻译出来的直接引用

  直接内存

    NIO可以使用Native函数库直接分配,这样能显著增加效率,因为不用在java堆和native堆中复制数据

    然而,分配内存时如果直接内存加java内存超过计算机物理内存限制,就会报出OutOfMemoryError

虚拟机对象:
对象的创建:
  1.new定义到常量池中的一个符号
  2.检查符号代表的类是否被装载 解析 初始化
    如果没有,加载类
  3.加载完类后,为新生对象分配内存(类加载后会确定分配的内存大小)

    内存分配方法:
      如果内存是规整的 指针碰撞(指针移动对象的内存大小的位置)
      如果内存是交错的 空闲列表 列表记录哪些内存是可用的,分配对象实例时分配给足够大的内存给对象,并更新列表

      选择哪种分配方法由java堆是否规整来决定,堆是否规整由java回收器是否采用压缩整理功能决定

    分配内存的线程安全问题
      对分配内存的动作进行同步处理
      TLAB 本地分配缓冲区 每个线程预先分配一块内存,哪个线程要分配内存,就在哪个线程上面分配,只有在TLAB用尽并分配新的TLAB时才需要同步锁
  4.内存分配之后,内存空间都初始化为零值
  5.对对象进行必要设置,设置对象头(类 元数据 hashcode gc年代)

对象的布局:
  对象头
    运行时数据
      HashCode GC分代年龄 锁状态标识 线程持有的锁 偏向线程id 偏向时间戳
    类型指针
      如果是数组,对象头要保存记录数组的长度信息
  实例数据
    虚拟机分配策略
  对齐填充
    hotpot虚拟机需要对象的大小是8个字节的整数倍 对象头正好是8个字节的倍数 如果实例数据没有对齐时,需要用对齐填充来补充

对象的访问定位:
  引用定义在栈上,虚拟机规范没有定义引用以何种方式定位对象位置,由虚拟机自身来完成,主流访问方式两种:
  1.句柄

    

    好处:对象移动时,只需要改变句柄的实例数据指针,不需要改变栈中本地变量的指针(它指向)

  2.直接指针

    

    好处 速度更快,节省一次指针定位的时间

OutOfMemoryError
java堆溢出:

  通过-XX:+HeapDumpOnOutOfMemoryError可以在虚拟机异常时候dump出当前堆转储快照以便事后分析
  VM Args:-Xms20m -Xmx20m -XX:+HeapDumpOutOfMemoryError

  MAT Tool插件安装

  内存转存储分析工具的Eclipse Memory Analyzer的使用

/**
*
*/
package com.gengsc.oom; /**
* VM args:-Xss2M
*
* @author shichaogeng
*
* 2017年6月26日
*/
public class JavaVMOOM { private void dontStop() {
while (true) {
//...
}
} public void StackLeakByThread() {
while (true) {
Thread thread = new Thread(new Runnable() {
public void run() {
dontStop();
}
});
thread.start();
}
} public static void main(String[] args) {
JavaVMOOM oom = new JavaVMOOM();
oom.StackLeakByThread();
}
}

通过不断的建立线程可以导致OutOfMemoryError

这种异常很奇特,为每个线程分配的内存越大,反而越容易产生内存溢出

这是什么原因呢,操作系统为每个进程分配内存是有限制的,减去Xms,减去MaxPermSize,剩下的就分给虚拟机栈和本地方法栈了,每个线程分配内存越大,线程数量越少,越易产生内存溢出异常

正确的处理方式就是减少java堆的大小和栈内存来换取线程数量。

方法区域和运行时常量池内存溢出:

String.intern()方法:当常量池中存在string时,返回这个字符串对象,不存在时,添加到常量池并返回字符串的引用。

关于String#intern()的详细内容可以点我

java内存区域及溢出异常的更多相关文章

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

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

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

    2.1 概述 对于从事C.C++程序开发的开发人员来说,在内存管理领域,他们即是拥有最高权力的皇帝又是执行最基础工作的劳动人民——拥有每一个对象的“所有权”,又担负着每一个对象生命开始到终结的维护责任 ...

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

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

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

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

  5. JVM高级特性与实践(一):Java内存区域 与 内存溢出异常

    套用<围城>中的一句话,“墙外面的人想进去,墙里面的人想出来”,用此来形容Java与C++之间这堵内存动态分配和垃圾收集技术所围成的“围墙”就再合适不过了. 对于从事C.C++的开发人员而 ...

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

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

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

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

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

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

  9. java内存区域与内存溢出异常(1)

    一. 运行时数据区域 java虚拟机在执行Java程序的过程中,会把它所管理的内存划分为若干个不同的数据区域偶 1.程序计数器 程序计数器是一块较小的内存空间,作用是当前线程所执行的字节码的行号指示器 ...

随机推荐

  1. 【Spark机器学习速成宝典】基础篇01Windows下spark开发环境搭建+sbt+idea(Scala版)

    注意: spark用2.1.1 scala用2.11.11 材料准备 spark安装包 JDK 8 IDEA开发工具 scala 2.11.8 (注:spark2.1.0环境于scala2.11环境开 ...

  2. OpenCV学习笔记(9)——形态学转换

    不同的形态学操作,例如腐蚀,膨胀,开运算,闭运算等 形态学操作是根据图像形状进行的简单操作.一般情况下对二值化图像进行操作.需要的参数有两个,一个是原始图像,第二个被称为结构化元素或核,它是用来决定操 ...

  3. react目录结构、demo实例详解、属性数据绑定方式

    1.目录结构 2.demo实例详解 a)创建Home.js import React, { Component } from 'react'; //创建一个组件必须要集成Component组件,且组件 ...

  4. 对redis的一些理解

    缓存就是在内存中存储的数据备份,当数据没有发生本质变化的时候,我们避免数据的查询操作直接连接数据库,而是去    内容中读取数据,这样就大大降低了数据库的读写次数,而且从内存中读数据的速度要比从数据库 ...

  5. Prometheus存储模型分析

    Prometheus是时下最为流行的开源监控解决方案,我们可以很轻松地以Prometheus为核心快速构建一套包含监控指标的抓取,存储,查询以及告警的完整监控系统.单个的Prometheus实例就能实 ...

  6. 6.3.2巴特沃斯(butterworth)低通滤波器

    在本程序中,共有六个自定义函数,分别是: 1. myMagnitude(Mat & complexImg,Mat & magnitudeImage),在该函数中封装了Opencv中的 ...

  7. select去掉默认样式

    今天遇到的问题,并在这里做一下记录和总结 去除select下拉框默认样式 select { /*Chrome和Firefox里面的边框是不一样的,所以复写了一下*/ border: solid 1px ...

  8. 在IOS系统中微信浏览器input输入框输入值无效

    [contenteditable="true"], input, textarea { -webkit-user-select: auto!important; -khtml-us ...

  9. Day01:API文档 / 字符串基本操作

    JDK API 什么是JDK API? JDK中包含大量的API类库,所谓AP就是一些写好的,可提供直接调用的功能(在Java语言中,这些功能以类的形式封装). JDK API包含的类库功能强大,经常 ...

  10. 项目连接oracle报错:listener does not currently know of SID given in connect descriptor

    今天练习用IDEA搭建了一个ssm框架,数据库是oracle,在执行mybatis-generator时,一直报错listener does not currently know of SID giv ...