橱柜网站源码,wordpress批量提交rss,网站备案账号是什么,网站优化有什么用JVM概述
JVM作用
java虚拟机负责装载字节码到其内部#xff0c;解释/编译为对应平台上的机器码指令执行#xff0c;通俗说就是将字节码转换为机器码
JVM内部构造
1、类加载部分#xff1a;负责把硬盘上的字节码加载到内存中#xff08;运行时数据区#xff09;
2、运…JVM概述
JVM作用
java虚拟机负责装载字节码到其内部解释/编译为对应平台上的机器码指令执行通俗说就是将字节码转换为机器码
JVM内部构造
1、类加载部分负责把硬盘上的字节码加载到内存中运行时数据区
2、运行时数据区负责存储运行时产生的各种数据类信息对象信息方法信息.....
3、执行引擎将字节码转为机器码
4、本地方法接口调用本地方法例如启动线程start0()还有Object类中的hashCode()--对象的内存地址还有文件操作中的read方法调用read0
5、垃圾回收部分
JVM类加载
类加载系统
类加载系统负责将硬盘上的字节码文件加载到JVM中生成类的Class对象存储在方法区。类就是一个模板。
类加载过程 1、加载
以二进制文件流进行读取在内存中为类生成Class文件
2、链接 验证检验被加载时的类是否有正确的内部结构并和其他类协调一致 准备为类的静态属性进行初始化赋值static和final先赋值为默认值在初始化阶段赋值为设置的指定值 解析将类中的符号引用替换为直接引用
3、初始化
初始化主要是为类的静态变量赋予正确的初始值类加载执行完初始化阶段才说明类加载完成了
类在哪些情况下会被加载 调用类中静态成员(变量方法) new 类的对象 在类中执行main() 反射加载类 class.forName(地址) 子类被加载会会导致父类初始化
类在以下两种情况下不会加载
1.类作为数组类型
Demo demo[] new Demo[10]; //new 的数组对象不是Demo对象
2.只是访问类中的静态常量
System.out.println(Demo.P); //优化 不是加载整个类只是获取到静态常量
类加载器
类加载器就是实际负责读取类的功能。
类加载器的分类
站在jvm的角度上分为引导加载器(不是用java写的是用c/c)负责读取加载java中底层系统库java写的类加载器
再细分类加载器可以分为 启动类加载器用c/c语言实现负责加载java的核心类库(系统库java.lang) 扩展类加载器用java语言实现继承ClassLoader类加载jre下面的扩展类的jre/lib/ext子目录 应用程序类加载器用java语言实现继承ClassLoader类用来加载我们自己开发的应用程序类
JVM运行时数据区
存储运行时产生的各种数据
程序计数器
程序计数器用来记录每一个线程执行的指令位置他的速度是最快的而且是线程私有的(每一个先线程都会有一个私有的程序计数器)此区域不会出现内存溢出(不够用),也不会出现垃圾回收
虚拟机栈
栈是运行的解决程序方法执行运行我们自己写的java方法
调用方法是方法入栈结束之后出栈
一个方法就是一个栈帧在栈帧中存储局部变量运行结果....
虚拟机栈也是线程私有的线程之间互相隔离
栈区域不存在垃圾回收但是会存在内存溢出的问题
栈帧中的内容 局部变量表int a 10 操作数栈(计算过程) ab 方法返回地址
本地方法栈
本地方法栈是用来执行调用的本地方法也是线程私有的不会存在垃圾回收可能会出现内存溢出的问题
堆内存
堆的概述
堆的作用是用来存储java语言中产生的对象
是运行时数据区中最大的一块内存空间这个空间可以自己设置。
堆空间是所有线程共享的
堆空间是垃圾回收的重点区域堆中没有被使用到的对象会被垃圾回收器回收掉
有可能出现内存溢出
堆内存的区域划分
堆分为新生区(新生代/年轻代)和老年区(老年代)
新生区又分为伊甸园区和幸存者0区幸存者1区
为什么要进行分区
可以将不同生命周期的对象存储在不同的区域针对不同的区域采取不同的垃圾回收算法使得垃圾回收策略更加优化 对象创建内存分配过程
新创建的对象都存储在伊甸园区
当垃圾回收时将还被使用的对象转移至某一个幸存者区将伊甸园区的垃圾对象进行清除
当下一次垃圾回收时将伊甸园区存活的对象与当前正在使用的幸存者区的对象转移到另一个幸存者区(每次会空闲一个幸存者区)
当一个对象经历过15次垃圾回收后仍然存活那么就把该对象移动到老年代
老年代比较少的进行垃圾回收在老年代空间不足时对老年代会进行垃圾回收
当回收后内存仍然不足时会触发FULL GC(整堆收集 应尽量避免)
当整堆收集后仍然不顾使用那么就出现内存溢出错误--OOM
JVM调优
可以根据程序具体使用场景对运行时数据区的各种空间大小进行调整例如堆方法区
方法区
主要用来存储加载的类信息
方法区的大小也是可以设置的
方法区也会进行垃圾回收也有可能出现内存溢出
方法区的垃圾回收
方法区的垃圾回收是对类的信息进行回收
类信息如果不再被使用类信息也可以被卸载
卸载条件该类所产生的对象不存在了该类的class对象也不再被使用加载该类的类加载器也被回收了
本地方法接口
是虚拟机中专门用来调用本地方法的接口
什么是本地方法
在java中被native关键字修饰的方法就是本地方法没有方法体不是用java语言实现的方法用c/c在操作系统底层实现的方法。
例如Object中的hashCode()获取对象的内存地址IO中读文件(输入文件 操作硬盘) read0()启动线程start0()就是把这个线程注册到操作系统中。
java中为什么要调用本地方法
因为java属于应用层语言有时候需要对硬件系统资源调用。
此时不方便在一个系统资源不允许对应用层程序直接调用
那么就需要通过本地方法去调用操作硬件资源
执行引擎
执行引擎是虚拟机中核心部件之一主要作用是将加载到虚拟中的字节码再次转换为机器码(字节码并不是系统能够直接执行的机器码)
执行引擎可以通过解释/编译两种方式实现将字节码转换为机器码
在java程序执行的过程中涉及两次编译
第一次是将源代码(.java)通过jdk调用编译器编译成.class文件称为前端编译
第二次通过执行引擎将字节码文件编译为机器码称为后端编译
将字节码转换为机器码有两种方式
解释器(解释执行)对字节码逐行进行翻译重复性代码也是每次都要解释执行效率低
编译器(编译执行)对某段字节码进行整体编译然后存储起来以后使用时就不需要在编译了效率高会针对执行过程中的热点代码进行编译并缓存起来。
为什么要使用解释执行和编译执行并行这样的设计
程序开始运行时解释器可以立即发挥作用投入使用而编译器虽然执行效率高但是前期需要对热点代码进行跟踪和编译需要消耗时间。
垃圾回收
什么时垃圾对象
就是一个对象不在被任何的引用所指向没有任何引用指向的对象垃圾对象如果不清理新的对象可能没有足够空间可能会导致内存溢出
垃圾回收发展
早期c/c这类语言内存管理都是手动的使用时申请使用完手动释放优点是对内存管理的更加精确效率更高缺点是增加程序员的负担控制不好容易出事(忘了释放误操作内存空间)
后来发展为自动回收javac#....都采用自动垃圾回收优点是解放了程序员缺点是占用了一定的内存空间(垃圾不是出现后立即回收)降低了程序员管理内存的能力。
哪些区域会出现垃圾回收
堆对象的回收 频繁回收年轻代较少回收老年代
方法区类信息的卸载 整堆收集时会进行回收
垃圾回收相关算法
垃圾标记阶段算法
垃圾标记阶段就是将虚拟机中不在被任何引用指向的对象标记出来在垃圾回收阶段就会将标记出来的对象进行回收。
引用计数算法(存在缺陷 没有被虚拟机所使用)
设计思想在对象中维护一个计数器变量当有引用指向对象时计数器加一相反引用断开就减一
优点设计思想简单容易分辨对象是否是垃圾对象
缺点需要维护一个变量存储引用数量频繁修改引用计数器的变量占空间且耗时最重要的是他无法解决循环引用问题。
可达性分析算法(根搜索算法)
设计思想从一些可以被称为GCRoots的对象开始向下查找只要某一个对象与GCRoots对象有联系就可以判断对象是被使用的与根对象引用链没有任何关系的就视为垃圾对象
哪些对象可以作为GCRoots(根对象) 虚拟机栈中(被调用的方法)所使用的对象 类中的静态属性 虚拟机中使用的系统类对象
Object类中的finalize()方法
这个方法是在这个对象要在对象被回收之前虚拟机自动调用的。
在对象回收前需要执行的一些操作就可以在此方法中编写
finalize方法可以在子类中重写
finalize方法只能调用一次(第一次被判定为垃圾要对其回收调用finalize对象有可能又被引用了对象就不能被回收当下次判定为垃圾对象时就不会在调用finalize)
生存还是死亡
由于finalize方法存在被标记为垃圾的对象也不是非死不可的可以将对象分为三种状态 可触及被GCRoots引用的不是垃圾对象 可复活的被判定为垃圾对象但是finalize方法还没有被调用过 不可触及的被判定为垃圾的finalize已经被调用过了
垃圾回收阶段算法
标记-复制算法
将内存分为多个较小的块当垃圾回收时将一个区域中存活的对象复制到另一个区域中在另一个区域从头开始排列清楚当前垃圾回收的区域 优点清理之后内存没有碎片
不足回收时需要移动对象所以适合小内存块而且存活对象较少的情况
标记-清除算法
将被标记为垃圾的对象地址进行记录后面如果分配新对象判断垃圾对象空间是否能够存储下新的对象如果能够存储下用新的对象直接覆盖垃圾即可存活对象是不发生移动的 优点不会移动对象
不足回收后内存中会出现碎片
标记-压缩(整理)算法
将存活的对象会移动到内存区域的一端按顺序进行排列(压缩)清理边界以外的空间
在标记清除的基础上进行一次内存整理
优点回收后没有内存碎片
标记-清除和标记-压缩的对比前者不会移动存活对象后者会移动存活对象但是两者都适合老年代对象回收
先使用标记清除算法当老年代空间不足时在使用标记压缩算法
垃圾回收时根据不同分区采用不同算法;新生代标记复制老年代标记清除和标记压缩
垃圾回收相关概念
内存溢出与内存泄漏
内存溢出简称OOM(OutOfMemory)简单来说就是内存不够用。
内存泄漏系统中那些用不到的但是又回收不到的对象
案例单例对象数据库连接对象IO流socket这些提供close()的类用完之后如果没有关闭垃圾回收器不能主动回收这些对象。
内存泄漏虽然不能直接触发内存溢出但是长期有对象不能被回收也是导致内存溢出的原因之一。
Stop the World
简称STW垃圾回收时会经历两个阶段一是标记阶段二是回收阶段在标记和回收时需要我们用户线程暂停不暂停标记和回收时可能会出现错标和漏标
垃圾回收器
概述
垃圾回收器是对垃圾回收过程的实现者不同的虚拟机中垃圾回收器的种类也很多
垃圾回收器的分类
从线程数量上分 单线程垃圾回收线程只有一个 多线程有多个垃圾回收线程
从工作模式上分 独占式垃圾回收线程执行时其他用户线程要暂停(STW) 并发式垃圾回收线程和用户线程可有做到并发执行
从分区角度上分 新生代 老年代
垃圾回收器性能指标
吞吐量运行用户代码的时间占总运行时间的比例总运行时间程序的运行时间内存回收的时间
用户线程暂停时间执行垃圾收集时程序的工作线程被暂停的时间。
回收时内存开销Java 堆区所占的内存大小
CMS回收器
开创了垃圾收集线程与用户下线程并发执行的先例并发标记清除 初始标记独占执行
并发标记并发执行
重新标记独占执行
并发清除并发执行
G1(Garbage First)回收器
G1垃圾回收器继承了CMS垃圾收集线程和用户线程并行执行的特点这样就减少了用户线程暂停的时间同时将新生代和老年代的各个区域又划分成了更小的区域对每个区域进行跟踪优先回收垃圾多的区域例如可以把伊甸园区可以划分成好几个小的区域。提高了回收效率和吞吐量不在区分年轻代和老年代可以做到对整个堆进行回收。非常适合服务端程序。