C++程序员肩负着每一个对象生命周期开始到终结的维护责任。Java程序员则可以借助自动内存管理机制,不需要自己手动去释放内存。由虚拟机进行内存管理,不容易出现内存泄漏和内存溢出的问题,但是一旦出现这些问题,就需要我们了解虚拟机的原理,才能排查解决这些内存问题。另外,jvm也是面试中常问的问题,因此我希望在者一系列的博客中进行相关内容的梳理。

jvm的知识主要分成三大板块:运行时数据区与垃圾回收,类的加载机制(重点是双亲委派模型等),Java内存模型与线程。

对于第一部分运行时数据区与垃圾回收,下面这个脑图总结的不错(来自朋友分享,未知出处,如果作者介意请在下方评论,我回删掉它)。

本篇是第一篇,首先来看一下什么是内存溢出?什么是内存泄漏?它们之间有什么区别和联系?

内存溢出和内存泄漏

内存溢出:程序运行过程中无法申请到足够内存,导致的错误。内存溢出通常发生与OLD段(老年代)或Perm段(永久代)垃圾回收后,仍然无内存空间容纳新的java对象的情况。

内存泄漏:程序中动态分配内存给一些临时对象,但是对象不会被GC回收,所以始终占用内存。及被分配的对象可达,但已经无用(由于主流的java虚拟机是通过可达性分析算法来标记垃圾对象的,因此如果是可达的对象,就不会被标记为垃圾,也不会被回收)

内存溢出与内存泄漏的关系:内存泄漏是内存溢出的一种原因。大量的内存泄漏会导致内存溢出。当然,内存溢出也可能是其他原因所导致的。

这里先简单介绍这两个概念,后续会有专门的博客阐述。


程序计数器(Program Counter)

注意:下文中凡是线程私有的运行时数据区,都不会涉及线程同步的问题。

程序技术器是线程私有的(为了线程切换后能恢复正确的执行位置,因此它必须是线程私有的)

作用:指示和记录线程的执行情况,字节码解释器工作时通过改变这个计数器的数值来选取下一条需要执行的字节码指令。它是当前线程所执行字节码的行号指示器。

注意:是唯一一个不会出现OOM异常的区域。

如果线程正在执行一个java方法,则这个计数器记录的是正在执行的虚拟机字节码的指令地址。如果是native方法,则该计数器为空。


虚拟机栈和本地方法栈 :

特点:线程私有

虚拟机栈的功能:每个方法在执行的时候都会在虚拟机栈中创建一个栈帧。栈帧存储内容:局部变量表,操作数栈,动态链接,方法出口等信息。每个方法执行到完成就对应了栈帧的压栈和出栈

注意,由于局部变量表是存放在虚拟机栈中,而虚拟机栈是线程私有的,所以局部变量都是线程安全的,局部变量不存在同步问题。

本地方法栈与虚拟机栈的区别:本地方法栈为native方法服务,虚拟机栈为java方法(也就是字节码)服务,有的虚拟机直接把这两个栈合二为一。

可能出现的异常:StackOverflowError和OutOfMemoryError


Java堆

特点:线程共享,java虚拟机管理内存中的最大一块内存。是垃圾收集器管理的主要区域。

作用:所有的对象实例和数组都在堆上分配内存。

现代收集器都采用分代收集算法,从内存回收角度看,可以分成新生代和老年代。

java堆可以处于物理上不连续的内存空间,只要逻辑上连续即可。

可能出现的异常:在堆中没有多余内存完成实例分配,而且堆也无法扩展时,将会抛出OutOfMemoryError异常。


方法区与运行时常量池

特点:线程共享。

功能作用:存放已经被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据。

java虚拟机规范对方法区的限制非常宽松。可以和堆一样不需要连续内存和可以选择固定大小和可扩展。,还可以选择不实现垃圾收集。方法区内存回收目标是针对常量池的回收和对类型的卸载。

方法区和运行时常量池可能出现的异常:OutOfMemoryError

运行时常量池:

功能:运行时常量池是方法区一部分,用于存放编译期生成的各种字面量和符号引用。翻译出来的直接引用也存储在运行时常量池中

特点:动态性。常量不一定只有编译期才能产生,运行期间也可能将新的常量放入池中。


直接内存

不是虚拟机运行时数据区的一部分,也不是java虚拟机规范中定义的内存区域。

jdk1.4引入了NIO,可以通过基于通道和缓冲区的IO方式,使用native函数库直接分配堆外内存(NIO也是一个重点,后续会有专门博客阐述)。这里我们只需要知道NIO是可以在堆外创建直接内存的。

可能出现的异常:OutOfMemoryError。


参考:https://blog.csdn.net/u012813201/article/details/73793668

   深入理解jvm

jvm系列(一)运行时数据区的更多相关文章

  1. JVM学习笔记-运行时数据区

    不同于C,C++程序,Java程序的内存管理工作由Java虚拟机(JVM)接管,这减低了java程序员的负担,但如果出现内存泄露与溢出问题如报OutOfMemory,StackOverFlow异常错误 ...

  2. 1、JVM 内存模型+运行时数据区+JVM参数

    JMM(内存模型)  1.’主内存+每个线程有自己的内存 JVM运行时数据区 包含:1.程序计算器(每个线程自带):2.JAVA-STACK(每个线程自带):3.本地方法stack:4.堆:5.方法区 ...

  3. jvm内存模型(运行时数据区)

    运行时数据区(runtime data area) jvm定义了几个运行时数据区,这些运行时数据区存储的数据,供开发者的应用或者jvm本身使用.按线程共享与否可以分为线程间共享和线程间独立. 线程间独 ...

  4. JVM三部曲之运行时数据区 (第一部)

    在接下来的几天想总结下,JVM相关的一些内容,比如下面的这三个内容算是比较核心知识点了 1.运行时数据区域: 在运行时数据区里存储类Class文件元数据(方法区),对象和数组(堆),方法参数局部变量( ...

  5. JVM内存结构——运行时数据区

    在Java虚拟机规范中将Java运行时数据划分为6种,分别为: PC寄存器(程序计数器) Java栈 堆 方法区 运行时常量池 本地方法栈 一.PC寄存器(程序计数器) PC寄存器(Program C ...

  6. JVM之Java运行时数据区(线程隔离区)

    来源 JVM会在会在执行Java程序过程中把所管理的内存划分为若干区域,主要包括程序计数器(Program Counter Register),虚拟机栈(VM Stack),本地方法栈(Native ...

  7. JVM之Java运行时数据区(线程共享区)

    JVM运行时区域各线程共享的区域包括堆区和方法区. 堆区 堆区最最主要的功能是存储对象实例[上篇也提到过],因此Java垃圾回收的主要战场就是在堆区,因此也有称为GC堆区.如果堆区的内存不够会出现Ou ...

  8. 【转】Java运行时数据区简介及堆与栈的区别

    理解JVM运行时的数据区是Java编程中的进阶部分.我们在开发中都遇到过一个很头疼的问题就是OutOfMemoryError(内存溢出错误),但是如果我们了解JVM的内部实现和其运行时的数据区的工作机 ...

  9. JVM系列之四:运行时数据区

    1. JVM架构图 Java虚拟机主要分为五大模块:类装载器子系统.运行时数据区.执行引擎.本地方法接口和垃圾收集模块. 2. JDK1.7内存模型-运行时数据区域 根据<Java 虚拟机规范( ...

随机推荐

  1. java安全编码指南之:序列化Serialization

    目录 简介 序列化简介 注意serialVersionUID writeObject和readObject readResolve和writeReplace 不要序列化内部类 如果类中有自定义变量,那 ...

  2. configfs_sample.c 理解

    1. 编译运行 代码从如下链接获得: https://github.com/torvalds/linux/blob/master/samples/configfs/configfs_sample.c ...

  3. scrapy反反爬虫

    反反爬虫相关机制 Some websites implement certain measures to prevent bots from crawling them, with varying d ...

  4. 处理textarea里Enter(回车换行符)

    Enter换行符 如果包含有回车换行符,在字符串中表现为"\n": 会返回一条字符串: 原文章:https://blog.csdn.net/shenlf_bk/article/de ...

  5. Java_包装类

    包装类 在实际应用中, 经常需要把基本数据类型转化为对象以便操作. 因此, Java在设计类时, 为每个基本数据类型设计了一个对应的类进行包装, 这样八个和基本数据类型对应的类统称为包装类(Wrapp ...

  6. 【Kata Daily 190910】Who likes it?(谁点了赞?)

    题目: Description: You probably know the "like" system from Facebook and other pages. People ...

  7. 谈谈对不同I/O模型的理解 (阻塞/非阻塞IO,同步/异步IO)

    一.关于I/O模型的问题 最近通过对ucore操作系统的学习,让我打开了操作系统内核这一黑盒子,与之前所学知识结合起来,解答了长久以来困扰我的关于I/O的一些问题. 1. 为什么redis能以单工作线 ...

  8. 剑指Offer-Python(16-20)

    16.合并另个排序链表 # -*- coding:utf-8 -*- class ListNode: def __init__(self, x): self.val = x self.next = N ...

  9. 解决 cannot resolve 依赖包的问题

    在maven import的时候 报这样的错误 之前也经常碰到这样的错误,通过reimport.清缓存等方法都可以解决.但这次试了好多次都还是这样,查看maven后发现我pom文件里也没写错. 最后是 ...

  10. 在Linux下安装C++的OpenCV 3

    最近在看<学习OpenCV3>这本书,所以记录下我在ubuntu16.4下搭建C++版本OpenCV 3.4.5的过程.首先请确保cuda,gcc, g++都安装好了,我这里是cuda 1 ...