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. 使用Flume-Taildir和rocketmq-flume与RocketMQ的结合

    一.Fume-Taidir Flume1.7.0加入了taildirSource作为agent的source.可以说是 Spooling Directory Source + Exec Source ...

  2. Loadrunner查询博客列表并循环删除博客列表中的所有博客

    Loadrunner查询博客列表并循环删除博客列表中的所有博客,在博客列表请求中使用关联,获取出列表中博客的数量,并找出博客列表请求的必要参数.关联使用Ordinal=All 找出所有匹配值 查找出所 ...

  3. electron-vue在使用element-ui时部分组件无法显示问题

    原文连接: https://juejin.im/post/5d132629e51d45772a49ad71 问题描述 在使用electron开发桌面系统时,遇到部分element-ui组件在页面中无法 ...

  4. https://www.jianshu.com/p/1038c6170775

    import os # 方法一: os.walk实现 def items_dir(rootname): l = [] for main_dir, dirs, file_name_list in os. ...

  5. 项目在服务器部署后打开出现Invalid Host header

    一.问题描述在服务器部署启动了项目,页面显示Invalid Host header. 二.问题分析新版的webpack-dev-server出于安全考虑,默认检查hostname,如果hostname ...

  6. svn"重新定位"提示版本库uuid不匹配

    svn"重新定位"提示版本库 uuid不匹配: 版本库 "https://wolfcome110/svn/andon" 的 uuid是 "d52648 ...

  7. 在Django中显示操作数据库的语句

    需要在配置中加上这个 LOGGING = { 'version':1, 'disable_existing_loggers':False, 'handlers':{ 'console':{ 'leve ...

  8. QQ自动强制加好友代码html

    鲜为人知的QQ自动强制加好友代码 是的,你也许见过强行聊天的代码: tencent://Message/?Uin=574201314&websiteName=www.oicqzone.com& ...

  9. 2019 CSP-J 游记(CQ LNBS考场 的退役之战)

    T0.10 爆零之战 已经不是第一次参加NOIP了(哦,关于兔子也NOIP了) 这次比赛的话,感觉考场很温馨,键盘很舒适,老师很友善,下次还会来.(哦不,下次来不了了,即将提前退役[大雾]) 刚刚文化 ...

  10. 初识阿里开源的本地Java进程监控调试工具arthas(阿尔萨斯)

    转载自:https://www.cnblogs.com/linhui0705/p/9795417.html 上个月,阿里开源了一个名为Arthas的监控工具.恰逢近期自己在写多线程处理业务,由此想到了 ...