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. Error-ASP.NET:未能加载文件或程序集“CMSCalendar”或它的某一个依赖项。系统找不到指定的文件。

    ylbtech-Error-ASP.NET:未能加载文件或程序集“CMSCalendar”或它的某一个依赖项.系统找不到指定的文件. 1.返回顶部 1. “/”应用程序中的服务器错误. 分析器错误 说 ...

  2. golang教材

    https://golangbot.com/buffered-channels-worker-pools/ https://golang.org/doc/ https://medium.com/go- ...

  3. PHPExcel 导出数据(xls或xlsx)- 助手类(函数)

    本文链接:https://www.cnblogs.com/tujia/p/11358096.html 说明:简单好用的导出助手,轻松导出数据到 excel !! 使用示例: Example: Exce ...

  4. sublime 光标由竖线变下横线

    编程时偶尔会突然出现光标突然间由“小竖线”变成“黑块矩形”,网上有说在控制面板中进行设置.由于光标是在使用中突然发生变化,推测是碰到了快捷键,因此断定有快捷键可以修改.后来,无意中碰到了“Insert ...

  5. [UE4] TSharedPtr, TWeakObjectPtr and TUniquePtr

    转自:https://dawnarc.com/2018/07/ue4-tsharedptr-tweakobjectptr-and-tuniqueptr/ UE4 的 TSharedPtr.TWeakO ...

  6. SpringBoot系列教程web篇之重定向

    原文地址: SpringBoot系列教程web篇之重定向 前面介绍了spring web篇数据返回的几种常用姿势,当我们在相应一个http请求时,除了直接返回数据之外,还有另一种常见的case -&g ...

  7. C++ 智能指针 std::auto_ptr 分析

    背景介绍: RAll机制 定义一个类来封装资源的分配和释放,在构造函数中完成资源的分配和初始化,在析构函数中完成资源的清理,从而保证资源的正确初始化和清理 ps:智能指针就是RAll机制的一种应用,智 ...

  8. zuul网关路由作用

    为了方便客户端调用微服务,所以设计出了网关.在微服务实例地址发生改变的情况下,客户端调用服务要能够不受影响. 网关可以完成的功能:路由,反向代理,日志记录,权限控制,限流 在本例子中 Eureka  ...

  9. vue中methods、computed、watch区别

    vue中methods.computed.watch区别methods:事件调用的钩子 computed:{ // 计算属性是根据他依赖的值计算的,当依赖值发生变化,其跟着改变 // 计算属性是依赖缓 ...

  10. 手撕面试官系列(六):并发+Netty+JVM+Linux面试专题

    并发面试专题 (面试题+答案领取方式见侧边栏) 现在有 T1.T2.T3 三个线程,你怎样保证 T2 在 T1 执行完后执行,T3 在 T2 执行完后执行? 在 Java 中 Lock 接口比 syn ...