工作室网站源码php,产品开发软件,apache 建立网站,网站开发系统有哪些开发方案JVM
整体组成部分
类加载器
类加载过程
加载#xff1a;使用IO读取字节码文件#xff0c;转换并存储#xff0c;为每个类创建一个Class对象#xff0c;存储在方法区中
链接#xff08;验证#xff0c;准备#xff0c;解析#xff09;
验证:对字节码文件格式进…JVM
整体组成部分
类加载器
类加载过程
加载使用IO读取字节码文件转换并存储为每个类创建一个Class对象存储在方法区中
链接验证准备解析
验证:对字节码文件格式进行验证文件是否被污染对基本的语法格式进行验证
准备为静态的变量进行内存分配赋值为默认值静态的常量在编译期间就进行初始化
解析将符号引用转为直接引用将字节码中的表现形式转为内存中表现内存地址
初始化
类的初始化为类中的定义静态变量进行赋值
类在什么时候会被初始化加载
1.在类中运行main方法
2.创建对象
3.使用类中静态常量、静态方法
4.使用反射
5.初始化它的子类
以下两种情况不会被初始化
1.使用编译期间被赋值的静态常量
2.作为数组类型
作用
负责从硬盘/网络中加载字节码信息加载到内存中运行时数据区的方法区中
启动类加载器
Bootstrap classLoader:主要负责加载核心的类库(java.lang.*等)构造ExtClassLoader和APPClassLoader。是由c/c编写的与Java语言无关
扩展类加载器
ExtClassLoader主要负责加载jre/lib/ext目录下的一些扩展的jar。
是由Java语言编写的
应用程序类加载器
AppClassLoader主要负责加载程序中自己开发的类
public class ClassLosderTest {public static void main(String[] args) {//启动类加载器ClassLoader a new String(a).getClass().getClassLoader();System.out.println(a);ClassLoader classLoader new ClassLosderTest().getClass().getClassLoader();//应用程序类加载器sun.misc.Launcher$AppClassLoader18b4aac2System.out.println(classLoader);//扩展类加载器 sun.misc.Launcher$ExtClassLoader1b6d3586System.out.println(classLoader.getParent());System.out.println(classLoader.getParent().getParent());}
}测试结果
null sun.misc.Launcher A p p C l a s s L o a d e r 18 b 4 a a c 2 s u n . m i s c . L a u n c h e r AppClassLoader18b4aac2 sun.misc.Launcher AppClassLoader18b4aac2sun.misc.LauncherExtClassLoader1b6d3586 null
运行时数据区
程序计数器是不会产生内存溢出的
堆和方法区是线程共享的是会出现垃圾回收的
程序计数器本地方法栈Java栈是线程私有的
堆方法区本地方法栈Java栈是可以进行内存大小设置的
堆方法区本地方法栈Java栈是会出现内存溢出的
Java栈stack
基本作用特征
栈是运行单位用来管理方法的调用运行是用来运行Java方法的区域可能会出现栈溢出是线程私有的
运行原理
是先进先出的结构最顶部的称为当前栈帧
栈帧结构
局部变量表存储方法中声明的变量
操作数栈实际计算运行
动态链接
方法返回地址
堆heap
基本作用特征
一个jvm只有一个堆是线程共享的堆内存的大小是可以调节的是用来存储对象的是内存空间最大的区域本区域是存在垃圾回收的
堆空间的分区
新生区
伊甸园区幸存0区幸存1区
永久区
为什么要分区
针对于不同的区可以使用不同的垃圾回收算法频繁回收新生代较少回收老年代
创建对象垃圾回收的过程
1.新创建的对象都存储在伊甸园区
2.当垃圾回收时将伊甸园区中的垃圾对象直接销毁将幸存下来的对象转移到幸存0区
3.当再次进行垃圾回收时将伊甸园区的幸存对象和幸存0区中的对象转移到幸存一区每次保证一个幸存者区为空
4.每次垃圾回收时幸存下来的对象都会记录幸存次数当一个对象经历15次垃圾回收仍然幸存下来就会被移动到老年区
5.老年区垃圾回收次数较少当内存空间不够用时才会进行回收老年区。
堆空间的配置比例
新生区和老年区内存占比默认为1:2
伊甸园区幸存0区幸存1区8:1:1默认
分代收集思想
Minnor GC 新生区收集经常发生
Major GC 老年区收集较少发生
整堆收集 对整个堆以及方法区进行收集发生情况老年区空间不足方法区空间不足System.gc()
字符串常量池
在JDK7之前位于方法区7之后位于堆空间中因为方法区的收集是在整堆收集时发生频率较低
方法区method area
静态变量常量类信息构造方法接口运行时的常量池类中各个元素的编号
(static final Class 常量池)
特点
jvm启动时创建大小可以调整是线程共享的会有内存溢出问题
方法区的垃圾回收
在full GC时发生主要是回收类信息发生的条件比较苛刻满足以下三点即可
1.在堆中该类的对象以及子类的对象不存在
2.该类的类加载器不存在
3.该类的Class对象不存在
程序计数器(program counter register)
每个线程都有一个程序计数器是线程私有的是一个非常小的内存空间几乎可以忽略不计是用来记录每个线程运行的指令位置是运行时数据区唯一不会内存溢出的一块空间运行速度最快
本地方法栈(native method stack)
每个线程私有用来运行本地方法的区域空间大小可以调整可能会出现栈溢出
执行引擎
作用
将加载到内存的字节码编译/解释为不同平台的机器码 .java文件----编译—.class文件 是在开发期间由jdk提供的编译器(javac)进行源码编译(前端编译)
.class文件----解释/编译—机器码 后端编译在运行时由执行引擎完成
解释器和编译器结合
解释器将字节码逐行进行解释执行效率低
编译器JIT将字节码编译并且在方法区中缓存起来执行更高效不会立即使用编译器将一些频繁执行的热点代码进行编译
程序启动后先使用解释器立即执行省去了编译时间
程序运行一段时间后对热点代码进行编译缓存为了后续提高效率
本地方法接口
什么是本地方法
凡是带了native关键字的说明Java的作用范围达不到会去调用本地方法接口没有方法体例如 hashCode() new thread().start()
为什么要用本地方法
JAVA语言需要和外部的环境进行交互(例如需要访问内存硬盘其他硬件设备)直接访问操作系统的接口即可
jvm中的一些机制
双亲委派机制
内容
当需要记载一个类时当前加载器不会先进行加载会向上委托父类加载器进行加载一直到启动类加载器如果启动类加载器无法加载就会通知子类进行加载一直到应用程序类加载器最终如果都没有找到就会抛出classnotfound异常
优点
安全性较高防止核心类库被修改避免了类的重复加载
如何打破双亲委派机制
创建自己的类加载器继承ClassLoader类并且重写里面的loadClass/findClass方法。
例如Tomcat使用自己的类加载器来加载类
垃圾回收
什么样的对象是垃圾
在运行过程中没有被任何引用指向的对象成为垃圾对象
为什么需要GC
如果不及时清理垃圾的话可能会出现内存溢出问题在回收时还可以将内存碎片进行整理
内存溢出和内存泄漏
内存溢出经过垃圾回收后还是无法存储新创建的对象内存不够用就是内存溢出
内存泄漏一些不用的对象但是jvm无法判定为垃圾不能进行垃圾回收默默占用内存这样的叫内存泄漏IO流close jdbc close
垃圾回收算法
标记阶段
作用: 判断对象是否是垃圾对象, 是否有引用指向对象.
相关的标记算法: 引用计数算法和可达性分析算法
引用计数算法(在现代的jvm中并没有被使用).
有个计数器来记录对象的引用数量
String s1 new String(aaa);
String s2 s1; //有两个引用变量指向aaa对象
s2 null; -1
s1 null; -1缺点:
需要维护计数器,占用空间,频繁操作需要事件开销
无法解决循环引用问题. 多个对象之间相互引用,没有其他外部引用指向他们,计数器都不为0,不能回收,产生内存泄漏.
可达性分析算法/根搜索算法
实现思路: 从一些为根对象(GCRoots)的对象出发去查找,与根据对象直接或间接连接的对象就是存活对象,不与根对象引用链连接的对象就是垃圾对象.
GC Roots 可以是哪些元素
在虚拟机栈中被使用的.
在方法中存储的静态成员指向的对象
作为同步锁使用的 synchronized
在虚拟机内部使用的对象
对象的 finalization 机制
当一个对象被标记为垃圾后,在真正被回收之前,会调用一次Object类中finalize(). 是否还有逻辑需要进行处理.
自己不要在程序中调用finalize(),留给垃圾回收器调用.
有了finalization机制的存在,在虚拟机中把对象状态分为3种:
1.可触及的 不是垃圾,与根对象连接的
2.可复活的 判定为垃圾了,但是还没有调用finalize(),(在finalize()中对象可能会复活)
3.不可触及的: 判定为垃圾了,finalize()也被执行过了,这种就是必须被回收的对象
垃圾回收阶段的算法
标记–复制算法:
将内存分为大小相等的两份空间, 把当前使用的空间中存活的对象 复制到另一个空间中, 将正在使用的空间中垃圾对象清除.
优点: 减少内存碎片
缺点: 如果需要复制的对象数量多,效率低.
适用场景: 存活对象少 新生代适合使用标记复制算法
标记-清除算法
清除不是真正的把垃圾对象清除掉,
将垃圾对象地址维护到一个空闲列表中,后面有新对象到来时,覆盖掉垃圾对象即可.
特点:
实现简单
效率低,回收后有碎片产生
标记-压缩算法(标记-整理)
垃圾回收器
垃圾收集器是垃圾回收的实际实现者,垃圾回收算法是方法论.
垃圾回收器分类
按照线程数量
单线程垃圾回收器
Serial
Serial old
多线程垃圾回收器
Parallel
按照工作模式分为
独占式: 垃圾回收线程执行时,其他线程暂停
并行式: 垃圾回收线程可以和用户线程同时执行
按工作的内存区间
年轻代垃圾回收器
老年代垃圾回收器
垃圾回收器性能指标
暂停时间
吞吐量
回收的速度
占用内存大小
CMS垃圾回收器
Concurrent Mark Sweep 并发标记清除
支持垃圾回收线程与用户线程并发(同时)执行
初始标记: 独占式的暂停用户线程
并发标记: 垃圾回收线程与用户线程并发(同时)执行
重新标记: 独占式的暂停用户线程
并发清除: 垃圾回收线程与用户线程并发(同时)执行 进行垃圾对象的清除
优点: 可以作到并发收集
弊端: 使用标记清除算法,会产生内存碎片, 并发执行影响到用户线程,无法处理浮动垃圾
三色标记
由于cms有并发执行过程,所以在标记垃圾对象时有不确定性.
所以在标记时,将对象分为3种颜色(3种状态)
黑色: 例如GCRoots 确定是存活的对象
灰色: 在黑色对象中关联的对象,其中还有未扫描完的, 之后还需要再次进行扫描
白色: 与黑色,灰色对象无关联的, 垃圾收集算法不可达的对象
标记过程:
1.先确立GCRoots, 把GCRoots标记为黑色
2.与GCRoots关联的对象标记为灰色
3.再次遍历灰色,灰色变为黑色,灰色下面有关联的对象,关联的对象变为灰色
4.最终保留黑色,灰色, 回收白色对象
可能会出现漏标,错标问题
G1(Garbage-First) 垃圾优先
将堆内存各个区又分成较小的多个区域, 对这些个区域进行监测,对某个区域中垃圾数量大的区域优先回收.也是并发收集的.