1.内存模型概述

  

2.运行时数据区

2.1.程序计数器

  理解:

  1.什么是程序计数器

  2.线程私有还是共享

  引入难点:

  理解什么是 native方法

 简单地讲,一个Native Method就是一个java调用非java代码的接口。
一个Native Method是这样一个java的方法:该方法的实现由非java语言实现,比如C。
这个特征并非java所特有,很多其它的编程语言都有这一机制,比如在C++中,你可以用extern "C"告知C++编译器去调用一个C的函数。
"A native method is a Java method whose implementation is provided by non-java code."
在定义一个native method时,并不提供实现体(有些像定义一个java interface),因为其实现体是由非java语言在外面实现的。,下面给了一个示例:
public class IHaveNatives
{
native public void Native1( int x ) ;
native static public long Native2() ;
native synchronized private float Native3( Object o ) ;
native void Native4( int[] ary ) throws Exception ;
}

2.2.java虚拟机栈

  https://www.cnblogs.com/newAndHui/p/11168791.html

2.3.本地方法栈

  本地方法栈(Native Method Stack) 与虚拟机栈所发挥的作用是相似的,

  他们之间的区别是:

  1.虚拟机栈为虚拟机执行java方法(也就是字节码)服务;

  2.本地方法栈则为虚拟机使用的Native方法服务.

  与虚拟机方法一样,本地方法栈区域也会就抛出StackOverflowError 和  OutOfMemoryErrory异常.

2.4.java堆

  

  1. Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建,是虚拟机所管理的内存中最大的一块。

此内存区域的唯一目的就是【存放对象实例和数组】,几乎所有的对象实例和数组都在这里分配内存。

  2. Java堆是垃圾收集器管理的主要区域,也称为GC 垃圾堆。后面会专门讲解GC算法。

  从内存回收的角度看,由于现在收集器基本都采用分代收集算法,所以Java堆可以细分为:新生代、老生代;

  从内存分配的角度看,线程共享的Java堆可能划分出多个线程私有的分配缓冲区(TLAB);

  不论如何划分,都与存放的内容无关,无论哪个区域,存储的仍然是对象实例和数组。

  3. 如果在堆中没有内存完成实例分配,并且堆上也无法再扩展时,将会抛出OutOfMemoryError异常。

  4. 内存泄露和内存溢出

  内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;

  内存泄露 memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。

  内存泄漏的累积最终会导致内存溢出!

  案例演示:

  参看:https://www.cnblogs.com/newAndHui/p/11105956.html 的 2.4节 内存快照分析

2.5.方法区

  

  1. 和堆一样,是各个线程共享的内存区域。它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

  2. Java虚拟机规范对方法区的限制非常宽松,除了和Java堆一样 不需要连续的内存和可以选择固定大小或者可扩展之外,还可以选择不实现垃圾回收。

  这区域的内存回收目标主要是针对常量池的回收和类型的卸载,

  一般而言,这个区域的内存回收比较难以令人满意,尤其是类型的回收,条件相当苛刻,但是这部分区域的内存回收确实是必要的。

  3. 很多开发者更愿意把方法区称为“永久代”(Perm Gen)(Permanent Generation)「总是存放不会轻易改变的内容」,

  原因:HotSpot的方法区也是采用的GC分代垃圾收集,省去了专门为方法区编写内存管理的工作。

  在目前已经发布的JDK 1.7 的HotSpot中,已经把原本放在永久代(方法区)的字符串常量池移至堆中。

  4. 运行时常量池(Runtime Constant Pool)是方法区的一部分(已移走)。

  5.JDK 1.8 中,已经没有方法区(永久代),而是将方法区直接放在一个与堆不相连的本地内存区域(Native Memory),这个区域被叫做元空间。

  6.当无法满足内存分配需求时:将会抛出OutOfMemoryError异常

2.6运行时常量池

  

  1. 运行时常量池是方法区的一个部分

  2. Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池(Constant Pool Table),用于存放编译期生成的字面量和符号引用,

  这部分内容(也可以称为 .Class文件中的静态常量池)将在类加载后进入方法区的运行时常量池中存放。

  字面量 : 比较接近Java语言层面的常量概念,如文本字符串、声明为final的常量值等。(final修饰的成员变量和类变量!「类变量即静态(成员)变量)」,也就是除final修饰的局部变量。

  符号引用 : 属于编译原理方面的概念,包括
    1.类和接口的全限定名(即路径,包名+类名)。
    2.字段的名称和描述符。
    3.方法的名称和描述符。
  当虚拟机运行时,需要从常量池获得对应的符号引号,再在类创建或运行时解析、翻译到具体的内存地址之中(直接引用)。

  3. 除了保存Class文件中描述的符号引用外,还会把编译出来的直接引用也存储在运行时常量池中。

  4. Java语言并不要求常量一定只有编译期才能生成,也就是并非置入Class文件中常量池的内容才能进入方法区运行时常量池,

  运行期间也可能将新的常量放入池中,这种特性被开发人员利用得比较多的便是String 类的intern()方法。

  5. 当常量池无法再申请到内存时也会抛出OutofMemoryError异常。

2.7直接内存

  

  1.并不是虚拟机运行时数据区的第一部分
  2.也不是java虚拟机规范中定义的内存区域
  3.直接内存分配不会受到java堆大小的限制,但受到本机总内存限制
  4.用处:直接使用Native函数分配该内存
  5.抛出OutofMemoryError异常

2.8扩展

  成员变量与局部变量

  成员变量 : 方法外部,类内部定义的变量;

  局部变量 : 方法或语句块内部定义的变量,必须初始化。

  1. 形参是局部变量,实参则可能是方法中的局部变量或全局变量。
  2. 栈内存中的局部变量随方法而生,随方法而灭。
  3. 成员变量存储在堆中的对象里,由垃圾收集器回收。

  

参考文献:

<<深入理解Java虚拟机:JVM高级特性与最佳实践>>

深入理解JVM-java内存区域与内存溢出异常的更多相关文章

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

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

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

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

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

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

  4. 深入理解java虚拟机-第二章:java内存区域与内存泄露异常

    2.1概述: java将内存的管理(主要是回收工作),交由jvm管理,确实很省事,但是一点jvm因内存出现问题,排查起来将会很困难,为了能够成为独当一面的大牛呢,自然要了解vm是怎么去使用内存的. 2 ...

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

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

  6. 深入理解Java虚拟机之Java内存区域与内存溢出异常

    Java内存区域与内存溢出异常 运行时数据区域 程序计数器 用于记录从内存执行的下一条指令的地址,线程私有的一小块内存,也是唯一不会报出OOM异常的区域 Java虚拟机栈 Java虚拟机栈(Java ...

  7. 深入理解Java虚拟机之图解Java内存区域与内存溢出异常

    Java内存区域与内存溢出异常 运行时数据区域 程序计数器 用于记录从内存执行的下一条指令的地址,线程私有的一小块内存,也是唯一不会报出OOM异常的区域 Java虚拟机栈 Java虚拟机栈(Java ...

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

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

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

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

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

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

随机推荐

  1. 笔记-JFB:业务流程梳理

    ylbtech-笔记-JFB:业务流程梳理 1.家政员找工作-->填写基本信息-->上岗申请--> 1.返回顶部 1. 2. 2. 2.返回顶部   3.返回顶部   4.返回顶部 ...

  2. DSCP 标

    DSCP差分服务代码点(Differentiated Services Code Point).它在每个数据包IP头部的服务类别TOS标识字节中,利用已使用的6比特和未使用的2比特,通过编码值来区分优 ...

  3. MySQL悲观

    //0.开始事务 begin;/begin work;/start transaction; (三者选一就可以) //1.查询出商品信息 for update; //2.根据商品信息生成订单 inse ...

  4. (原)x264代码中的码流控制学习

    (本文主要是自己的学习笔记,如果有误,请留言,一起讨论和更正.)这里采用x264的代码进行走读的方式,来学习qp在码流控制中过程. 在ABR模式下,当我们设置一个bitrate的平均码率以后,x264 ...

  5. koa2 post请求ctx.request.body空获取不到的解决办法

    header请求头添加Content-type: application/json

  6. java上传文件类型检测

    在进行文件上传时,特别是向普通用户开放文件上传功能时,需要对上传文件的格式进行控制,以防止黑客将病毒脚本上传.单纯的将文件名的类型进行截取的方式非常容易遭到破解,上传者只需要将病毒改换文件名便可以完成 ...

  7. Redis Sentinel 高可用部署实践集群

    一.Redis Sentinel 介绍    1.Sentinel     数据库环境搭建,从单机版到主备.再到多数据库集群,我们需要一个高可用的监控:比如Mysql中,我们可能会采用MHA来搭建我们 ...

  8. 002 spring boot框架,引入mybatis-generator插件,自动生成Mapper和Entity

    1.创建一个springboot项目 2.创建项目的文件结构以及jdk的版本 3.选择项目所需要的依赖 点击next,直到项目构建完成. 4.项目初步结构 5.POM文件 <?xml versi ...

  9. python学习-33 max和min函数的高级使用

    1.简单比较 age_dic={'age1456':15,'age2':16,'xiaohong_age':12,'xiaoming_age4':18,'age5':10} print(max(age ...

  10. C指针的一些小细节

    1  int *c;*c=4-->int *c;int b;c=&b;*c=4; 在使用指针之前,一定要将其初始化,当然,如果是赋予一个地址,就相当于使用的同时就进行了初始化.