1.java内存模型 / java运行时数据区模型?

元空间属于本地内存 而非JVM内存

内存模型

程序计数器

1.作为字节码的行号指示器,字节码解释器通过程序计数器来确定下一步要执行的字节码指令,比如:顺序执行,选择,循环,异常处理等。

2.程序计数器属于线程私有,当线程切换有切回来的时候程序计数器还记着它之前执行到哪一行指令了,可以接着执行。

程序计数器是唯一一个不会出现 OutOfMemoryError 的内存区域,程序计算器所维护的就是下一条待执行的命令的地址,它的生命周期随着线程的创建而创建,随着线程的结束而死亡。

java虚拟机栈

可能出现两种异常:

StackOverFlowError: 若栈的内存大小不允许动态扩展(hotspot),那么当线程请求栈的深度超过当前 Java 虚拟机栈的最大深度的时候,就抛出 StackOverFlowError 错误。

OutOfMemoryError: 如果栈的内存大小可以动态扩展(Classic), 如果虚拟机在动态扩展栈时无法申请到足够的内存空间,则抛出OutOfMemoryError异常。

java虚拟机栈是线程私有的,与线程的生命周期同步,主要描述的是方法执行的内存模型。由一个个栈帧组成。

每个方法执行都会创建一个栈帧。也是先进后出的顺序。

每个栈帧包括:局部变量表、操作数栈、动态链接、方法返回地址。

https://blog.51cto.com/u_15334563/3473150

局部变量表:用来存储编译器可知的类型(基本数据类型、对象引用(reference))

 操作数栈:是的方法调用的中转站,用来存放方法和执行过程产生的中间计算结果和计算过程的临时变量。

 动态链接:在一个方法调用另外一个方法时,将符号引用转换为直接引用的过程。(java源文件被编译成字节码时,所有的变量、方法引用都作为符号引用保存在了Class文件的常量池里)

 方法返回地址:用于存放调用该方法的pc寄存器的值,方法结束后出栈过程,恢复上层方法的栈帧信息(恢复上层方法的局部变量表、操作数栈、将返回值入调用者栈帧的操作数栈、设置PC寄存器值等,让调用者方法继续执行下去)

本地方法栈

和java虚拟栈功能类似。java虚拟机栈服务于java方法,本地方法栈服务于本地方法。也由栈帧组成,栈帧包括本地变量表、操作数栈、动态链接、出口信息。在hotspot里。本地方法栈和java虚拟栈合二为一了。

堆是jvm里面最大的一块内存区域,也是垃圾回收器主要工作的场所。几乎所有的对象实例和数组都存放在堆内存里。但是有一些对象实例可以不放在堆里,而放在栈里面。因为这些对象是方法私有的,他们在方法里面被创建,但是没有逃逸出去(未返回,也未被外部引用)。

从 JDK 1.7 开始已经默认开启逃逸分析。

逃逸分析://TODO

堆内存模型:

jdk1.7及以前:堆内存主要由三部分组成:新生代、老年代、永久代组成

jdk1.8:堆内存主要由两部分组成:新生代、老年代。

而之前永久代存放的东西被元空间代替。存放到了直接内存。

“永久代与堆内存存在于连续的物理内存上,可以看作是从堆内存中拿出一部分内存作为永久代,但是两者又是互相隔离的,所以永久代称为非堆,此时永久代的大小受限于堆内存的大小,因为永久代是从堆内存拿的空间,逻辑上是与堆内存连在一起的”

为什么要用元空间取代永久代?

1.减少OOM

因为永久代配置的内存大小是有限的(jvm为永久代设置了一个大小),如果动态生成很多class的时候,很有可能出现java.lang.OutOfMemoryError:PermGen space错误。

2.方便合并 HotSpot 和 JRockit 的代码,Rockit没有永久代的概念。

 堆内存容易发生的OutOfMemoryError 异常

  1. java.lang.OutOfMemoryError: GC Overhead Limit Exceeded : 当 JVM 花太多时间执行垃圾回收并且只能回收很少的堆空间时,就会发生此错误。
  2. java.lang.OutOfMemoryError: Java heap space 新建对象,内存空间不够的时候。

方法区(是逻辑区域)

永久代:

1.7之前 字符串常量池、静态变量、类信息、运行时常量池、JIT代码缓存

1.7 类信息、运行时常量池、JIT代码缓存  (字符串常量池、静态变量被移到了堆了)

1.8没了  被元空间取代了

JDK 1.7 为什么要将字符串常量池移动到堆中

主要是因为永久代(方法区实现)的 GC 回收效率太低,只有在整堆收集 (Full GC)的时候才会被执行 GC。Java 程序中通常会有大量的被创建的字符串等待回收,将字符串常量池放到堆中,能够更高效及时地回收字符串内存。

方法区常用参数有哪些?

JDK 1.8 之前永久代还没被彻底移除的时候通常通过下面这些参数来调节方法区大小。

-XX:PermSize=N //方法区 (永久代) 初始大小
-XX:MaxPermSize=N //方法区 (永久代) 最大大小,超过这个值将会抛出 OutOfMemoryError 异常:java.lang.OutOfMemoryError: PermGen

相对而言,垃圾收集行为在这个区域是比较少出现的,但并非数据进入方法区后就“永久存在”了。

JDK 1.8 的时候,方法区(HotSpot 的永久代)被彻底移除了(JDK1.7 就已经开始了),取而代之是元空间,元空间使用的是直接内存。下面是一些常用参数:

-XX:MetaspaceSize=N //设置 Metaspace 的初始(和最小大小)
-XX:MaxMetaspaceSize=N //设置 Metaspace 的最大大小 默认unlimited

与永久代很大的不同就是,如果不指定大小的话,随着更多类的创建,虚拟机会耗尽所有可用的系统内存。

直接内存

不属于jvm运行时数据区,也不是jvm规范中定义的内存区域。但是会被频繁使用,也可能出现OOM. 不受jvm内存的限制,但是会收到本机总空间内存和处理器寻址空间的限制。

NIO的应用

NIO引入的channel和buffer的方式,可以直接使用本地函数分配堆外内存,然后通过堆中的DirectByteBuffer 对象作为这块内存的引用进行操作,避免了java堆和本地堆来回复制数据,提高了性能。

2.对象的创建过程

类加载检查->分配内存->设置默认初始值->设置对象头->执行init方法

3.对象的内存布局

对象头:第一部分用于存储对象自身的运行时数据(哈希码、GC 分代年龄、锁状态标志等等),另一部分是类型指针,即对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。

实例数据

对齐填充:Hotspot 虚拟机的自动内存管理系统要求对象起始地址必须是 8 字节的整数倍

4.对象的访问定位

句柄:局部变量表里面reference保存句柄的地址,根据堆里面的句柄(包含对象实例数据地址和对象类型数据地址),找堆里的实例数据和方法区的类信息->修改对象信息,不用修改栈

直接指针:局部变量表里面reference保存对象的地址,直接找到堆里面的对象实例数据,再从堆里面对象类型数据的指针找方法区的类信息->查找速度快

面试-JVM的更多相关文章

  1. java面试——jvm

    背景:用来总结java面试过程中与jvm相关的问题. 垃圾回收以及优化总结 <JVM 垃圾回收器工作原理及使用实例介绍> 介绍常用的垃圾回收算法,垃圾收集器,垃圾收集器相关的调试参数. J ...

  2. 【面试 JVM】【第六篇】JVM调优

    六部分内容: 一.内存模型 1.程序计数器,方法区,堆,栈,本地方法栈的作用,保存那些数据 可以画个大图出来,很清晰 jvm内存模型主要指运行时的数据区,包括5个部分. 栈也叫方法栈,是线程私有的,线 ...

  3. 不止面试—jvm类加载面试题详解

    面试题 带着问题学习是最高效的,本次我们将尝试回答以下问题: 什么是类的加载? 哪些情况会触发类的加载? 讲一下JVM加载一个类的过程 什么时候会为变量分配内存? JVM的类加载机制是什么? 双亲委派 ...

  4. [jvm][面试]JVM 调优总结

    https://blog.csdn.net/wfh6732/article/details/57422967 堆大小设置JVM 中最大堆大小有三方面限制:相关操作系统的数据模型(32-bt还是64-b ...

  5. 不止面试-JVM垃圾回收面试题详解

    第一部分:面试题 本次分享我们将尝试回答以下问题: GC 是什么? 为什么要有 GC? 简单说一下java的垃圾回收机制. JVM的常见垃圾回收算法有哪些? 为什么要使用分代回收机制? 如何判断一个对 ...

  6. Java面试- JVM 内存模型讲解

    经常有人会有这么一个疑惑,难道 Java 开发就一定要懂得 JVM 的原理吗?我不懂 JVM ,但我照样可以开发.确实,但如果懂得了 JVM ,可以让你在技术的这条路上走的更远一些. JVM 的重要性 ...

  7. java面试-JVM内存结构

    一.JVM内存结构 二.类加载(classLoader)机制 java中的ClassLoader详解 java类加载机制面试题 java类加载机制面试题 虚拟机把描述类的数据从Class文件加载到内存 ...

  8. java面试-JVM常用的基本配置参数有哪些?

    1.-Xms 初始大小内存,默认为物理内存 1/64,等价于 -XX:InitialHeapSize 2.-Xmx 最大分配内存,默认为物理内存的 1/4,等价于 -XX:MaxHeapSize 3. ...

  9. java面试-JVM调优和参数配置,如何查看JVM系统参数默认值

    一.JVM的参数类型: 1.标配参数: java -version java -help 2.X参数: -Xmixed 混合模式(先编译后执行) -Xint  解释执行 -Xcomp 第一次使用就编译 ...

  10. 面试~jvm(JVM内存结构、类加载、双亲委派机制、对象分配,了解垃圾回收)

    一.JVM内存结构 ▷ 谈及内存结构各个部分的数据交互过程:还可以再谈及生命周期.数据共享:是否GC.是否OOM 答:jvm 内存结构包括程序计数器.虚拟机栈.本地方法栈.堆.方法区:它是字节码运行时 ...

随机推荐

  1. idea安装破解

    转 一般都会去官网下载,官网地址IntelliJ IDEA,官网上对于不同的操作系统(windows,macOS,Linux)都有两个版本可供下载 3|0安装 确认已经安装好了 JDK ,每个IDEA ...

  2. git 与远程仓库关联返回 fatal: remote origin already exists 解决方法

    今天领导新建了一个代码仓库,我按照流程一步步推送代码,结果到了关联仓库的时候,返回 fatal: remote origin already exists(远程源已经存在) 下面是解决方法 1.删除远 ...

  3. ETL常用的三种工具介绍及对比Datastage,Informatica和Kettle

    https://blog.csdn.net/qq_34901049/article/details/103676959 大数据量下Informatica与Datastage的处理速度是比较快的,比较稳 ...

  4. feign的工作原理

    1.开发微服务时,我们会在微服务的主程序入口添加EnableFignClient注解开启对Feign Client扫描加载处理,根据FignClient接口规范,定义接口并加上FignClient注解 ...

  5. K8S kubectl命令

    一.kubectl命令 1. 格式:kubectl [command] [type] [name] [flag] command:资源执行的操作,如create.get.delete: type:指定 ...

  6. Unity异步加载场景与加载进度条

    先上效果图 需要三个场景 1,2, 3 从场景1跳转到场景3,场景2是加载场景 场景1按钮的代码如下 using System.Collections; using System.Collection ...

  7. bootstrap-select使用、relation-graph使用

    bootstrap-select 这里要实现的是带有搜索功能的select框, bootstrap 官网没有可以直接拿来用的.如下是官网给出的解释,带搜索功能的select需要自定义. 在网上找到了有 ...

  8. java redis 获取key 剩余时间

    /** * 查询key的生命周期 * @param key redis 存数据的键 * @return 默认单位秒,也可以自行传入单位 */public long getKeyExpire(Strin ...

  9. XSStrike-20220320

    Usage: xsstrike.py [-h] [-u TARGET] [--data PARAMDATA] [-e ENCODE] [--fuzzer] [--update] [--timeout ...

  10. pycharm 安装步骤

    1.双击安装包 2.点击next 3.选择安装目录后点击next进入下一步 4.根据你电脑的实际情况选择安装32位还是64位 5.勾选 .py 后即可点击next进入下一步 6.默认,直接next 7 ...