JVM基础知识整理----体系结构和运行时数据区
JVM
java概述
java体系
- java程序语言
- java虚拟机实现
- class文件格式
- java类库api
- 第三方类库
- javaSE
- javaEE
- javaME
java历史
1991年4月 James Gosling博士领导的绿色计划(Green Project)开始启动 java的前身oak 95年的互联网兴起
1995年5月23日。Oak语言改名为Java,并且在SunWorld大会上正式发布Java 1.0版本。Java语言第一次提出了“Write Once,Run Anywhere”的口号。
1996年1月23日,JDK 1.0发布,Java语言有了第一个正式版本的运行环境。JDK 1.0提供了一个纯 解释执行的Java虚拟机实现(Sun Classic VM)。JDK 1.0版本的代表技术包括:Java虚拟机、Applet、 AWT等。
1996年4月,十个最主要的操作系统和计算机供应商声明将在其产品中嵌入Java技术。同年9月, 已有大约8.3万个网页应用了Java技术来制作。在1996年5月底,Sun于美国旧金山举行了首届JavaOne大会,从此JavaOne成为全世界数百万Java语言开发者每年一度的技术盛会。
1997年2月19日,Sun公司发布了JDK 1.1,Java里许多最基础的技术支撑点(如JDBC等)都是在 JDK1.1版本中提出的,JDK 1.1版的技术代表有:JAR文件格式、JDBC、JavaBeans、RMI等。Java语言的语法也有了一定的增强,如内部类(Inner Class)和反射(Reflection)都是在这时候出现的。
直到1999年4月8日,JDK 1.1一共发布了1.1.0至1.1.8这9个版本。从1.1.4以后,每个JDK版本都有 一个属于自己的名字(工程代号),分别为:JDK 1.1.4-Sparkler(宝石)、JDK 1.1.5-Pumpkin(南瓜)、JDK 1.1.6-Abigail(阿比盖尔,女子名)、JDK 1.1.7-Brutus(布鲁图,古罗马政治家和将军) 和JDK 1.1.8-Chelsea(切尔西,城市名)。
java虚拟机家族
- 虚拟机始祖:Sun Classic/Exact VM
- 武林盟主:HotSpot VM
- 小家碧玉:Mobile/Embedded VM
- 天下第二:BEA JRockit/IBM J9 VM
- 软硬合璧:BEA Liquid VM/Azul VM
- 挑战者:Apache Harmony/Google Android Dalvik VM
- 没有成功,但并非失败:Microsoft JVM及其他
JAVA内存区域和内存溢出异常
JAVA内存分配
线程独享
- 虚拟机栈
- 栈根
- 方法访问的时候有相关的逻辑
- 局部变量表
- 字符串数组长度知道,存储的指针或者句柄,32位,长度时固定的。访问的时候需要限定为指针和句柄(对象数组也是这样的)
- 栈根
- 本地方法栈
- 本地方法—native方法 一般C++写
- 程序计数器
- 每个线程的方法不一样
- 执行的字节码的行号机器
- 流程控制的指示器
- 为线程切换之后能正确的执行位置 所有需要没有线程有一个独立的线程计数器,互不影响
- 唯一没有内存溢出错误的区域
线程共享
- 方法区
- 类型信息
- static 修饰 final 修饰
- 回收性价比很低
- 堆
- 垃圾回收
- int a = 3
- 分场景存储
- 普通方法 入栈
- 类中 入堆 在对象创建时进入
运行时常量池表
是方法区的一部分 。存放字面量和符号引用 如String a = “aaaaa” 其中的aaaaa就是字面变量
可以在运行期间可以将新的常量进入池中。最多在String类的intern()方法。
当常量池无法申请到内存会抛出异常
直接内存
- -Xmx 参数
hotspot虚拟机
对象创建
- 遇到new指令之后,检查参数可不可以定位到类的符号
- 如果有
- 如果没有
- 通过之后
- 分配内存
- 如果java堆时绝对规整的则指针碰撞
- 如果java堆时一块一块的 则 使用空闲列表
- 带有控件压缩整理 就是指针碰撞 简单高效
- 清除算法 空间列表
- 可能线程不安全 可以使用TLAB分配空间,预先分配一块内存。使用完了采用同步锁定
- TLAB 通过-xx :+/-UserTLAB参数设定
- 内存分配完了 就是将分配的控件初始话为零(对象头不用),如果使用TLAB可以在分配时同时完成
- 局部变量没有初始值,成员变量有初始值。
对象内存布局
- 对象头
- 对象运行时数据(Markword)
- 哈希码
- GC粉黛年两
- 锁状态标记
- 线程持有的所
- 动态的定义数据结构,可以复用
- 对象指向它的类型元数据的指针
- 知道属于那个类型的
- 通过对象所属类的信息
- 对象运行时数据(Markword)
实例数据
- 实际储存对象的有效信息
- 根据一个规定好的顺序排序
- 父类优先
- 子类可以父类的空隙中
对其填充
- 实际数据可能不够
对象的定位
句柄
- 好处
- 对象移动时会好
- 句柄池
- 指向类型
- 指向实例
- 实例单独存放
直接指针(hotspot使用)
- 移动需要修改java栈中的数据
- 好处
- 移动快
- java栈直接指向存储实例,并且其中有一个指向类型的指针
垃圾回收和内存分配策略
三问
- 那些内存需要回收
- 什么时候回收
- 如何回收
当高并发习引起错误是需要堆监控和调节
那些该回收
- 活着
- 死去
两种方法
引用计数器
- 虽然需要一些额外的控件计数
- 但是效率高
- java没有使用
- 缺点
- 很难解决对象的循环引用问题
- 比如对象内相互指向但是外部实例置为空了
可达性分析算法
使用GC root作为根节点,如果节点不可达及为死亡
虚拟机栈 引用的对象
方法去京台面两引用的对象
方法去常量引用的对象
本地方法栈中国JNI应用的对象
java虚拟机内部的应用
- 基本数据对应的Class对象,常驻异常对象
所有被同步持有的对象
反映java虚拟机内部情况的JM XBean,JVM TI中注册的回调,本地代码。
支持局部回收的特征,需要将关联的都添加到GC Roots 避免过多做过优化
四种引用
- 强引用
- 只要有就绝不回收
- 当内存不够就报错
- 软引用
- 有用但是非必须
- 在内存溢出之前会回收
- 如果还不够就抛出异常
- 弱引用
- 垃圾回收就会被回收
- 虚引用
- 在被回收之后有一个系统通知
- 完成一个实例,并且在java中找一下应用的实例。为什么这么设计?
对象的自我拯救
public static void main(String[] args) throws Throwable {SAVE_HOOK = new Main();SAVE_HOOK = null;System.gc();Thread.sleep(500);if(SAVE_HOOK != null){SAVE_HOOK.isAlive();}else{System.out.println("no,i am dead");}SAVE_HOOK = null;System.gc();Thread.sleep(500);if(SAVE_HOOK != null){SAVE_HOOK.isAlive();}else{System.out.println("i not dead once , but now,i am dead");}}public static Main SAVE_HOOK = null;public void isAlive(){System.out.println("yes,i am stall alive");}@Overrideprotected void finalize() throws Throwable{super.finalize();System.out.println("finalize if executed");Main.SAVE_HOOK = this;}
- 如上 对象第一次拯救成功,因为重写了finalize方法,在第一次回收会执行他自己的finalize方法。第二次在回收就必定会被回收。所有对象的fianlize方法之后被执行一次。
垃圾回收不是立即执行的,想队列添加一个,优先级很低
回收方法区
常量回收
类型
- 所有实例都被回收
- 类加载器都被回收了
- java。lang Class对象没有在任何地方被引用,无法通过反射访问该类的方法
Java虚拟机被允许对满足上述三个条件的无用类进行回收,这里说的仅仅是“被允许”,而并不是
和对象一样,没有引用了就必然会回收。关于是否要对类型进行回收,HotSpot虚拟机提供了-
Xnoclassgc参数进行控制,还可以使用-verbose:class以及-XX:+TraceClass-Loading、-XX:
+TraceClassUnLoading查看类加载和卸载信息,其中-verbose:class和-XX:+TraceClassLoading可以在
Product版的虚拟机中使用,-XX:+TraceClassUnLoading参数需要FastDebug版[1]的虚拟机支持。
JVM基础知识整理----体系结构和运行时数据区相关推荐
- java中判断undefined_Java虚拟机系列一:一文搞懂 JVM 架构和运行时数据区
前言 之前写博客一直比较随性,主题也很随意,就是想到什么写什么,对什么感兴趣就写什么.虽然写起来无拘无束,自在随意,但也带来了一些问题,每次写完一篇后就要去纠结下一篇到底写什么,看来选择太多也不是好事 ...
- jvm运行时类加载机制_JVM体系结构:JVM类加载器和运行时数据区
jvm运行时类加载机制 各位读者好! 在JVM系列的上一篇文章中,开发人员了解了Java虚拟机(JVM)及其体系结构. 本教程将帮助开发人员正确回答以下主题的问题: ClassLoader子系统 运行 ...
- JVM体系结构:JVM类加载器和运行时数据区
各位读者好! 在JVM系列的上一篇文章中,开发人员了解了Java虚拟机(JVM)及其体系结构. 本教程将帮助开发人员正确回答以下主题的问题: ClassLoader子系统 运行时数据区 1.简介 在继 ...
- jvm的类加载和运行时数据区和垃圾回收
类加载过程 加载(loading) 引导类加载器 扩展类加载器 系统类加载器 1.通过一个类的全限定名获取此类的二进制字节流 2.将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构 3.在内 ...
- 一文搞懂JVM架构和运行时数据区,全网最新
1.Java基础面试知识点 Java中==和equals和hashCode的区别 int.char.long各占多少字节数 int与integer的区别 探探对Java多态的理解 String.Str ...
- 想自学Java的速来!一文搞懂JVM架构和运行时数据区,满满干货指导
前言 Java是目前应用最为广泛的软件开发平台之一.随着Java以及Java社区平台的不断壮大,Java也早已不再是简简单单的一门计算机语言了,它更是一个平台.一种文化.一个社区. 作为一个平台,Ja ...
- JVM内存与垃圾回收-3-运行时数据区/虚拟机栈/RA(返回地址)
是什么 虚拟机栈/栈帧/RA 正常退出:调用方法PC寄存器的数值即调用该方法的下一条指令的地址 异常退出:方法内部发生异常但此异常没有在异常表中,导致异常退出 区别-正常退出与异常退出:异常退出不会给 ...
- Web前端基础知识整理
1. 前端基础知识 文件分类 XML(扩展标记语言) 装载有格式的数据信息,用于各个框架和技术的配置文件描述 特点: 扩展名为.xml 内容区分大小写 标签要成对出现,形成容器,只能有一个 标签按正确 ...
- JVM基础知识和调优
JVM基础知识和调优 什么是垃圾 当一个对象有人引用它时,那么就不是垃圾,不然就不是垃圾 如何辨别一个对象是不是垃圾 计数(最基础的),有一个对象引用就记一个数(i++)问题,循环引用 GC root ...
最新文章
- 路由 php mysql_Php 连接 MySQL 的三种方式
- EShop网上商城项目(一)
- python语言入门pdf-Python编程从入门到精通.pdf
- DPDK加速I/O虚拟化
- 利用回溯法解决1-9之间添加+或-或使得运算结果为100的问题
- 梅山启动建设智慧管网 为城市管理者提供智能决策支持
- linux内核奇遇记之md源代码解读之一
- 三大邮箱品牌:网易,腾讯,阿里说明
- win10无线投屏花屏
- MATLAB:数值微积分
- 用强化学习制作游戏AI
- 楼板的弹性计算和塑形计算_板计算的时候什么时候用弹性计算
- 学习笔记 | Orillusion-WebGPU小白入门(六)
- 一文看懂智慧城市,解码25万亿大市场的机遇与格局
- 基于opencv与android的手机远程监控
- 照度计的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
- 【2019/07/20测试 T2】切题
- python训练opencb分类器_垃圾邮件分类.ipynb
- php掷骰子游戏,js实现简单掷骰子小游戏
- Unity Bolt