JVM内存区域划分

这篇具有很好参考价值的文章主要介绍了JVM内存区域划分。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


简介:JVM有很多个不同版本的实现;其中HotSpot VM是最主流使用的JVM;Oracle官方jdk和开源openjdk都是使用这个JVM

JVM内存区域划分

JVM内存区域划分:按每个区域不同功能划分;相互之间不会干扰
JVM内存区域划分,java-se,jvm,类加载

本地方法栈

native:表示是JVM内部C++代码;给调用JVM内部方法准备的栈空间。存储本地方法native之间调用相关的信息。每个线程都有一份;还会有其它方法参数、返回地址、局部变量等等很多元素。

程序计数器

记录当前线程执行到哪个指令;每一个线程都有一份

虚拟机栈(和本地方法栈类似)

给java代码使用的栈;存的是方法之间的调用关系;还会有其它方法参数、返回地址、局部变量等等元素。也是一个线程有一份。
栈帧:每一个方法里对应一个栈帧;里面存的这个方法相关的东西。这里栈帧的空间是连续的(JVM有参数可以设置栈空间大小;超过范围就会栈溢出;栈溢出指单个的栈帧溢出;死递归就非常容易栈溢出)
存活时间:这里的内存和方法相关的;调用一个方法就会创建栈帧;方法执行结束;栈帧销毁
栈是私有的吗?
变量捕获:也能访问;所以说栈是私有的是不严谨。应该说每个线程有自己私有的栈;而不是是栈是私有的;

堆区

堆:整个JVM空间最大区域;new出来的对象都在堆上;类的成员变量也都是在堆上。一个进程只有一份;所有线程共用一个
一个我们上面的原始图就是一个进程;每一个java进程就是上面的这样一个JVM
JVM内存区域划分,java-se,jvm,类加载
两个进程为什么不共用一个JVM?
只能说很难办;那就别办了。操作系统办好了;但是不好办的;而java进程恰好是隔离性做好的;直接用现成的就好了;这样子不必处理就能有隔离性;让他们不会互相影响。

元数据区(以前叫方法区)

元:meta;属性。所以类对象这在这里;注意是类对象;是static?不限于static(方法的字节码和运行时数据都存在方法区)
类对象:常量池(放在元数据区好处;编译器确定;不再修改;让多个对象共享就有利于节省空间)、静态成员
字符串之所以在常量池的好处:这是一种特殊类型;编译器就确定;而且保持不变;并且可以被多个对象共享;所以放在这里有利于节省空间
方法区也是一个线程只有一块;然后多个线程共用;
public final :可能被编译器优化成字面值常量(就在常量池里);也可能没有优化;看你有没有加static。

JVM类加载机制

类加载过程

类加载:.class文件从硬盘加载到内存(元数据区;能在程序运行时快速访问和使用类的这些信息)过程
JVM内存区域划分,java-se,jvm,类加载
加载:找到这个.class文件的过程;打开文件;读文件内容
验证:检查.class文件的格式是否符要求;官方规范文档上详细描述.class格式
准备:给类对象分配内存空间(相当于先占个位置;内存初始化全0)
解析:针对字符串常量进行初始化;把符号转为引用
初始化:针对类对象的内容进行初始化内存空间;还有加载、执行静态代码块代码

解析这里把符号转为引用是什么意思呢?
字符串常量,得有一块内存空间,存这个字符的实际内容还得有一个引用,来保存这个内存空间的起始地址
在类加载之前,字符串常量,此时是处在 .class 文件中的此时这个“引用”记录的并非是字符串常量的真正的地址;可以认为是个占位符。类加载后才把字符串常量放到内存中;这时候才有真正的内存地址;这个引用才能被真正赋值到正确的内存地址

双亲委派模型:描述加载找.class的基本过程
三个类加载器:
1:BootstrapClassLoader负责加载标准库中的类((java 规范要求提供哪些类;无论是哪种JVM 的实现都会提供这些一样的类)
2:ExtensionClassLoader 负责加载JVM 扩展库中的类(不同JVM实现的厂商会做不同扩展一些额外功能)
3:ApplicationClassLoader 负责加载用户提供的第三方库/用户项目代码中的类

它们存在一个父子关系;爷爷、爸爸、孙子。不是继承那个父子关系;而相当于每一个class loader有一个parent属性指向自己的父类加载器
类似递归逻辑:
首先加载从 ApplicationClassLoader 开始;是 ApplicationClassLoader 会把加载任务交给父亲;而 ExtensionClassLoader 要去加载了;他又委托给自己的父亲BootstrapClassLoader 要去加载了。BootstrapClassLoader 也想委托自己的父亲结果发现,自己的父亲是 null;没有父亲/父亲加载完了,没找着类,才由自己进行加载。
父类没找到就让子类去找;如果到ApplicationClassLoader还没找到就抛出类找不到的异常

为什么要设置这个查找顺序:
1:假设用户自己写一个java.lang.String类;按这个加载顺序不会说加载时候会让你的类代替人家标准库的类
2:用户自定义的类加载器;也可以加入上述流程;跟一个类似链表一样;把自己写的类加载器挂到它们上面;这样子类加载可能扩展了

破坏双亲委派模型:
我们不一定要遵循双亲模型;自己写的类加载器也可以不遵守;看需求是什么;比如Tomcat加载webapp是单独类加载器;不遵守双亲委派模型

什么时候触发类加载呢?

一个类只有真正被用到才加载(懒汉模式);但是加载过后;后续就不必重复加载;那么什么时候才算被用到呢?
例如:创建对象、调用静态方法等
你要调用静态属性;当然是要依赖于类对象;new对象跟建房子一样;你得要有图纸文章来源地址https://www.toymoban.com/news/detail-658404.html

到了这里,关于JVM内存区域划分的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • JVM——Java 内存区域详解

    如果没有特殊说明,都是针对的是 HotSpot 虚拟机。 基本问题 介绍下 Java 内存区域(运行时数据区) Java 对象的创建过程(五步,建议能默写出来并且要知道每一步虚拟机做了什么) 对象的访问定位的两种方式(句柄和直接指针两种方式) 拓展问题 String 类和常量池 8 种基本

    2024年02月13日
    浏览(43)
  • JVM篇--Java内存区域高频面试题

    首先我们要知道java堆空间的产生过程: 即当通过java命令启动java进程的时候,就会为它分配内存,而分配内存的一部分就会用于创建堆空间,而当程序中创建对象的时候 就会从堆空间来分配内存,所以堆空间存放的主要是对象和数组; 而GC 其实说白了就是java虚拟机回收对象

    2024年02月01日
    浏览(52)
  • 深入理解 JVM 之——Java 内存区域与溢出异常

    更好的阅读体验 huge{color{red}{更好的阅读体验}} 更好的阅读体验 本篇为深入理解 Java 虚拟机第二章内容,推荐在学习前先掌握基础的 Linux 操作、编译原理、计算机组成原理等计算机基础以及扎实的 C/C++ 功底。 该系列的 GitHub 仓库:https://github.com/Doge2077/learn-jvm Java 虚拟机在

    2024年02月09日
    浏览(64)
  • JVM零基础到高级实战之Java内存区域本地方法栈

    JVM零基础到高级实战之Java内存区域本地方法栈 JVM零基础到高级实战之Java内存区域本地方法栈 本地方法栈是什么? 用于作用域本地方法执行的一块Java内存区域 为什么要有本地方法栈? 与Java虚拟机栈相同,每个方法在执行的同时都会创建一个栈帧(Stack Framel)用于存储局部

    2024年02月09日
    浏览(42)
  • jvm对象内存划分

    jvm内存空间是逻辑上连续的虚拟地址空间(虚拟内存中的概念)映射到物理内存(不一定连续),物理内存不足时还会将物理内存中的数据交换到swap(磁盘的一块区域)。 这块水有点深,查阅资料做了个个人的总结。 内存划分,有 指针碰撞 和 空闲列表 这两种划分方式: 1、

    2024年02月07日
    浏览(46)
  • 【JVM】JVM五大内存区域介绍

    目录  一、程序计数器(线程私有) 二、java虚拟机栈(线程私有) 2.1、虚拟机栈 2.2、栈相关测试 2.2.1、栈溢出 三、本地方法栈(线程私有) 四、java堆(线程共享) 五、方法区(线程共享) 六、实例演示         Java虚拟机在执行Java程序的过程中会把它所管理的内存划

    2024年02月15日
    浏览(43)
  • 【Java高级应用:深入探索Java编程的强大功能,JVM 类加载机制, JVM 内存模型,垃圾回收机制,JVM 字节码执行,异常处理机制】

    本人详解 作者:王文峰,参加过 CSDN 2020年度博客之星,《Java王大师王天师》 公众号:JAVA开发王大师,专注于天道酬勤的 Java 开发问题 中国国学、传统文化和代码爱好者的程序人生,期待你的关注和支持!本人外号:神秘小峯 山峯 转载说明:务必注明来源(注明:作者:

    2024年01月16日
    浏览(91)
  • jvm的内存区域

    JVM 内存分为线程私有区和线程共享区,其中方法区和堆是线程共享区,虚拟机栈、本地方法栈和程序计数器是线程隔离的数据区。 1)程序计数器 程序计数器(Program Counter Register)也被称为 PC 寄存器,是一块较小的内存空间。 它可以看作是当前线程所执行的字节码的行号指

    2024年02月10日
    浏览(40)
  • JVM内存区域

    为了更好的理解类加载和垃圾回收,先要了解一下JVM的内存区域(如果没有特殊说明,都是针对的是 HotSpot 虚拟机。)。 Java 源代码文件经过编译器编译后生成字节码文件,然后交给 JVM 的类加载器,加载完毕后,交给执行引擎执行。在整个执行的过程中,JVM 会用一块空间来

    2024年02月13日
    浏览(45)
  • Java进阶(1)——JVM的内存分配 & 反射Class类的类对象 & 创建对象的几种方式 & 类加载(何时进入内存JVM)& 注解 & 反射+注解的案例

    1.java运行时的内存分配,创建对象时内存分配; 2.类加载的顺序,创建一个唯一的类的类对象; 3.创建对象的方式,new,Class.forName,clone; 4.什么时候加载.class文件进入JVM内存中,看到new,Class.forName; 5.如何加载?双亲委托(委派)机制:安全;AppClassLoader; 6.反射实质:能

    2024年02月14日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包