目录
[1.JVM 简介](#1.JVM 简介)
[2、JVM 运⾏时数据区](#2、JVM 运⾏时数据区)
1.JVM 简介
JVM 是 Java Virtual Machine 的简称,意为 Java虚拟机。 虚拟机是指通过软件模拟的具有完整硬件功能的、运⾏在⼀个完全隔离的环境中的完整计算机系统。 常⻅的虚拟机:JVM、VMwave、Virtual Box。
其实是仿照一个真实的机器或操作系统,操作系统里对进程地址空间进行了划分区域,因此jvm也进行了内存划分
2、JVM 运⾏时数据区
JVM 运⾏时数据区域也叫内存布局,但需要注意的是它和 Java 内存模型((Java Memory Model,简 称 JMM)完全不同,属于完全不同的两个概念,它由以下 5 ⼤部分组成:
1、程序计数器(线程私有)
记录当前指令执行到哪个地址
2、元数据区(线程共享)
保存当前类加载好的数据,.java=>.class=>加载到内存中,运行这个代码就需要把.class加载到内存里面即后面说的类加载机制
3、Java虚拟机栈(线程私有)
保存方法调用的关系,写代码会有方法调用,每次调用方法就会进入到方法内部执行,每次执行完毕,就会返回到调用位置,这是c++方法栈
然后在C++的代码中构建了一个JVM虚拟机程序,通过这些C++代码,解释执行.class的字节码执行字节码,又会涉及到java的方法调用,通过上面c++代码又构造java栈

同时Java有些时候会调用C++代码,例如Thread.sleep
此外,栈的空间不是特别大一般几mb,可以通过JVM启动参数配置
4、堆(线程共享)

如果t是一个局部变量,t就在栈上,
如果t是一个成员变量,t就在堆上
如果t是一个静态成员变量,t就是在元数据区

元数据和堆整个Java进程公用一个,程序计数器和栈,每个线程有一个
3、JVM类加载
类加载很复杂,从面试角度主要关注两个
1、类加载步骤有哪些
a)加载:找到.class文件,通过累的全限定名 包名+类名 Java.lang.String,打开文件读取内容到内存
b)验证:解析校验.class文件读到的内容是否合法,并把这里内容加载转换成结构化数据

c)准备给类对象申请内存空间,申请的内存空间相当于全0的空间
d)解析针对字符串常量进行初始化~字符串常量本身在.class文件中,通过解析文件的字符串常量放到内存空间里(元数据区,常量池)
e)初始化,针对刚的类对象进行最终的初始化,针对类对象的各种属性进行填充,包括类中的静态成员,如果这个类还有父类,这个环节也会触发加载父类
2、类加载的双亲委派模型是
单亲委派,父亲委派
类加载器,JVM中有专门的模块负责加载类JVM提供了三类加载器

这三个类加载器,首当其冲的就是要进行"找.class文件"环节~com.bit.xxxx.Test给定一个类名,类似于java.lang.String
双亲委派模型的过程:进行类加载,通过全限定类名,找.class的时候就会从ApplicationClassLoader 作为入口开始,然后把加载类这样的任务,委托给父亲来进行,ExtensionClassLoaderExtensionClassLoader 也不会立即进行查找,而是也委托给父亲来进行, BootstrapClassLoaderBootstrapClassLoader 也想委托给父亲,由于没有父亲,只能自己进行类加载.根据类名,找标准库范围,是否存在匹配的.class 文件加载,没找到就抛出异BootstrapClassLoader 没有找到,再把任务还给孩子 ExtensionClassLoader,接下来ExtensionClassLoader 来负责进行.cass 件的过程.找到就加载,没找到,也就把任务还给孩ApplicationClassLoader.接下来ApplicationClassLoader 负责找.class.找到就抛出异常

4、GC垃圾回收
在c语言当中需要手动释放指针,Java里面引入了GC垃圾回收机制
1、找到垃圾(不再使用的对象)
1)引用计数,python php使用,每个对象在new的时候,都搭配一个小的内存空间保存一个整数,每次通过引用计算有多少个引用

缺点1,内存消耗更多吗,如果引用计数4字节,引用本身8字节
2、循环引用问题,如下列代码

2)可达性分析 Java采取这个
1、以代码中的一些特定对象,作为遍历的起点=》GCRoots,
如1栈上的局部变量
2常量池引用指向的对象 程序运行到任何一个时候,JVM都是容易获取到~
3静态成员引用类型
2、尽可能遍历,判断对象能否访问到

3、每一次访问到一个对象,都会把这个对象标记为可达,当完成所有对象遍历之后,未被标记成可达对象就是要回收的垃圾
2、释放垃圾(对于的内存释放)
当知道那些对象是垃圾,如何释放呢
1、标记清理,
把垃圾对象的内存,直接进行释放,但是这样会产生内存碎片问题

虽然空闲空间很多,但是申请一个稍微大一点的内存就会失败,如总内存4g,申请1g可能会失败
2、复制算法

缺点1、内存的空间利用率很低,2一旦垃圾对象不是很多,复制成本很高
3、标记-整理

类似顺序表搬运,但是开销很大
4JVM采用分代回收
某个对象,经历一轮gc可达性分析之后不是垃圾,此时对象年龄+1

如果某个对象已经是一个年龄很大的对象了,此时大概率还会存在很久,如果一个对象是年轻,这个对象可能存在不久,如果是年龄大,可能会一直存在,对于年轻对象可以频繁gc,对于老年对象减少gc次数

新产生的对象放到伊甸区,绝大部分伊甸区对象活不过第一轮gc,通过复制算法将存活对象复制到幸存区,幸存区也会经历gc扫描,释放一大堆对象,剩下的对象再次通过复制算法复制到另一个幸存区,如果这个对象在幸存区经历了多次复制,存活下来,就会放到老年代
