Java虚拟机内存模型
章节
- JVM结构
- 运行时数据区(Java run time data area)
- 方法区-线程共享
- 堆区 -线程共享
- Java栈 -线程私有
- native 本地方法栈-线程私有
- PC寄存器 - 线程私有
- 类加载器子系统
- ClassLoader 概述
- 类加载时机
- ClassLoader 分类
- ClassLoader 工作原理
- 装载
- 链接
- 初始化
- 执行引擎
1. JVM结构
1、JVM 主要由类加载器、Java运行时数据区、执行引擎以及本地方法接口组成。 2、Java 运行时数据区由 方法区、堆、Java栈、PC寄存器、本地方法栈组成。 3、本地方法栈、PC寄存器、Java栈是由每个线程私有的;方法区、堆是所有java线程共享的。
2.运行时数据区
2.1 Java 栈
1.Java栈与线程关联在一起,new Thread() 后会为当前线程创建对应的Java栈。 2.每个Java 栈中会包含多个栈帧,每个栈帧与每个运行中的方法对应起来。 3.运行一个方法创建一个栈帧,方法运行结束,栈帧弹出栈顶。
2.1.1 局部变量区
局部变量区 包含 方法参数、和局部变量、基本类型变量、对象引用。
2.1.2 操作数栈
进行入栈出栈基本操作。在计算时,操作数栈出栈,计算完毕后再入栈。
2.1.3 帧数据区
1.记录 存储类的相关信息的常量池的 指针 ,便于解析。 2.帮助方法正常返回:恢复调用该方法的栈帧、设置PC寄存器指向 调用方法对应的下一条指令、把返回值压入调用方法的栈帧中的操作 数栈中。
2.2 本地方法栈
本地方法栈类似于Java栈,主要存储本地方法调用状态。 本地方法栈为JVM调用native方法服务。
2.3 PC寄存器/程序计数器
记录当前线程即将执行的下一条指令的地址。
2.4 方法区
类型信息和类的静态变量都存储在方法区中 方法区中每个类存储了以下数据: 1.类及其父类的全限定名 2.类的类型 class or interface 3.访问的修饰符 (public abstract final) 4.实现的接口的全限定名的列表 5.字段信息 6.方法信息 7.静态变量 8.常量池 9.ClassLoader 引用 10.Class引用
注意:可见类的所有信息都存储在方法区中,由于方法区是线程共享的,所以必须保证线程安全。
举例:两个类要同时加载一个尚未被加载的类,那么一个类会请求它 的ClassLoader去加载需要的类,另一个类只能等待而不会重复加 载。
2.4.1 常量池
常量池本身是方法区中的一个数据结构: 1、常量池中存储了如字符串(有些地方称之为字符串池)、final 变量值,类名和方法名常量。 2.常量池中数据在编译器就被确定,保存在.class文件中。 分为两类: 字面量:final变量、字符串 引用量:类名、方法名、类和接口的全限定名 3.方法区对应持久代(Permanent Generation),默认大小16M,最大值 64M。大小通过参数来设置,-XX:permSize 指定初始值,-XX:MaxPermSize 指定最大值。
2.5 堆
1.堆是JVM管理的内存中最大的一块,是被所有Java线程共享的, 不是线程安全的,在JVM启动时创建。 2.堆用于存储对象实例以及数组值。 3.堆中有指向方法区中常量池中类信息的指针 4.堆中存放了指向方法表的指针 5.堆中实例数据包含了对象锁 monitor 对象,
2.5.1 分代管理模式-新生代、老年代
1.新生代(New Generation) 大多数情况下对象被分配在新生代,新生代由Eden Space 和两块相同大小的Survivor Space 组成。 后两者主要用于Minor GC 时的对象复制。 2.老年代 (Old Generation/Tenuring Generation) 在新生代存活时间较久的对象会被转入老年代,老年代进行垃圾回收的频率没有新生代高。
3.类加载器子系统(Class Loader)
3.1 类加载器概述
类加载器子系统负责加载编译好的.class 字节码文件,一般情况下类 在编译成.class 文件之后,立即被装入内存,使JVM可以实例化或以 其他方式使用加载后的类。JVM的类加载子系统支持在运行时的动态 加载(Java 反射),动态加载可以节省内存空间。
3.2 类加载的时机
类加载时机 | 含义 | 举例 |
---|---|---|
静态加载 | 静态加载类,在编译时刻就需要加载所有可能使用到的类 | 如 new Word() |
动态加载 | 属于延迟加载的模式,在java反射中会用到,首先节省内存,另外一个是动态加载类,这种方式在动态工厂方法中也会用到,这个生成类的util类只需要被加载一次就可以了 | 如 class.forName this.getClass() Class.class 三种方式实现运行时加载 |
3.3 ClassLoader 分类
- 1.启动类加载器 (Bootstrap ClassLoader),java rt.jar 负责加载java 核心类
- 2.扩展类加载器 (Extension ClassLoader),负责加载一些扩展功能的jar包
- 3.系统类加载器 (System ClassLoader ),负责加载启动参数中制定的ClassPath 中的jar 包及目录。我们自己写的Java类也是由该ClassLoader加载的。
- 4.用户自定义类加载器 (UserDefined Classloader):用户自定义类的加载规则,可以手动控制加载过程中的步骤。
3.4 ClassLoader的工作原理
类加载分为三个过程:装载、链接、初始化
3.4.1 装载
1. 通过类的全限定名和Classloader 加载类,主要是将指定的.class 文件加载至jvm当中,类加载之后,jvm内部使用类的全限定名+ ClassLoader实例ID 标明类。 2.ClassLoader 实例 与 类实例位于堆中,他们的类信息位于方法区中 3.装载过程使用“ 双亲委派模型”,当一个ClassLoader要加载类时,他 会先请求他的双亲ClassLoader,即整个加载类的请求不断上抛,直 到启动类加载器。只有其双亲ClassLoader无法加载指定的类时,它 才会自己加载类。 4.不同类加载器之间是无法交互的,即使是同一个类,被不同的 ClassLoader加载,他们也无法感知彼此的存在。
3.4.2 链接
1.验证:校验.class文件的正确性,确保改文件是符合规范定义的 2.准备:为类分配内存,同时初始化类中的静态变量赋值为默认值。 3.解析:主要把类的常量池中的符号引用解析为直接引用。
3.4.3 初始化
定义:初始化类中的静态变量,并执行类中的static代码,构造函数。
初始化类的时机
1.通过new关键字、反射、clone、反序列化机制实例化对象 2.调用类的静态方法 3.使用类的静态变量或对其赋值 4.通过反射调用类的方法 5.初始化该类子类,其父类必须已经被初始化 6.具有main方法的类。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
(转载)Java8新的日期API LocalDate, LocalTime
前言 由于Java Date的各种问题,Java8推出了新的日期API,很受一拨人的追捧。 为什么我们需要新的Java日期/时间API? 在开始研究Java 8日期/时间API之前,让我们先来看一下为什么我们需要这样一个新的API。在Java中,现有的与日期和时间相关的类存在诸多问题,其中有: Java的日期/时间类的定义并不一致,在java.util和java.sql的包中都有日期类,此外用于格式化和解析的类在java.text包中定义。 java.util.Date同时包含日期和时间,而java.sql.Date仅包含日期,将其纳入java.sql包并不合理。另外这两个类都有相同的名字,这本身就是一个非常糟糕的设计。 对于时间、时间戳、格式化以及解析,并没有一些明确定义的类。对于格式化和解析的需求,我们有java.text.DateFormat抽象类,但通常情况下,SimpleDateFormat类被用于此类需求。 所有的日期类都是可变的,因此他们都不是线程安全的,这是Java日期类最大的问题之一。 日期类并不提供国际化,没有时区支持,因此Java引入了java.util.Cale...
- 下一篇
分享一些 Java 后端的个人干货
学习 Java 也有了不少时间,入 Java 后台的坑也有了一段时日。这段时间里,听过许多前辈的经验与分享,也看过许多大佬的文章和作品。找了个时间整理和总结了一下我个人到目前为止一路以来的听到看到或者自己感悟到的干货。 这篇文章可能更多的是面对初学者,当然,只要有人看了我的这篇文章后能有所收获,我就心满意足了。 本文主要有那么几个部分: 学习路线 推荐一些书籍和公众号 推荐一些网站,工具和资料 一. 学习路线 对于想往 java 后台这个方向发展的同学,可以按照以下路线入门: 先把 java 基础部分学完,重点关注多态继承等面向对象的概念,异常,IO,容器等,这部分建议通过视频来学习(毕向东,马士兵老师等的视频都是很经典的,虽然可能年代稍久远,但是万变不离其宗)。有些人可能会推荐看书来学习(如《head first java》等),但是个人认为,如果对于初学者,看书可能相对来说比较难理解,也很容易出现看不下去的情况,而许多优秀的教学视频更加生动,也更加容易理解。 然后就可以开始 javaweb 的学习了,Jsp,Servlet 相对来说比较老旧,但是对于初学者理解 HTTP 请求,理解...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
-
Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8编译安装MySQL8.0.19
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
推荐阅读
最新文章
- SpringBoot2全家桶,快速入门学习开发网站教程
- Linux系统CentOS6、CentOS7手动修改IP地址
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS6,CentOS7官方镜像安装Oracle11G
- SpringBoot2整合Redis,开启缓存,提高访问速度
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作