【进阶】JVM篇

打印 上一主题 下一主题

主题 939|帖子 939|积分 2817

为什么学习jvm
1、面试的需要
学过java的步伐员对jvm应该不陌生,步伐员为什么要学习jvm呢?其实不懂jvm也可以照样写出优质的代码,但是不懂jvm会被大厂的面试官虐的体无完肤。
2、高级步伐员需要了解
jvm作用

jvm负责把编译后的字节码转换为机器码
jvm内部构造

1.类加载部门:负责把硬盘上字节码加载到内存中(运行时数据区)
2.运行时数据区:负责存储运行时产生的各种数据 类信息,对象信息,方法信息……
3.执行引擎:负责将字节码转为机器码
4.本地方法接口:调用本地方法, Object类中的 hashCode()--拿对象的内存地点
public native int hashCode();
private native int read0() throw IOEception;
垃圾接纳部门

jvm类加载系统

1.类加载子系统概述

类加载器子系统负责从文件系统或者网络中加载class文件,类加载系统只负责class文件的加载,至于它是否可以运行,则由执行引擎决定。
加载的类信息存放于一块称为方法区的内存空间

类加载系统,负责将硬盘上的字节码文件加载到jvm中,天生类的Class对象,存储在方法区。
类就是一个模板
2、类加载过程

1.加载

以二进制字符流举行读取
在内存中为类天生Class对象
2.链接

·验证:检验被加载的类是否有正确的内部结构,并和其他类协调同等;
·预备 为类的静态属性举行初始化的赋值
预备阶段 先赋值为默认0 在初始化阶段赋值为‘123’
·解析 把字节码的符号引用 更换成 内存中的直接引用地点

3.初始化

初始化阶段主要是为类中的静态成员举行赋值
因为类加载执行完初始化阶段,才说明类加载完成了。
类在哪些环境下会被加载

调用类中静态成员(变量,方法)
new关键字调用
执行该类的main()
反射加载类 Class class.forName("地点");
子类被加载

类在以下两种环境下,是不会被加载的

  
  1. 1.类作为数组类型 Demo[] demo = new Demo[10]; //new的数组对象   不是Demo对象
  2. 2.只是访问类中的静态的常量 System.out.println(Demo.P);// 优化 不加载整个类了,只获取到用到的静态常量
复制代码
类加载器

类加载器就是实际负责读取类的功能

类加载器分类:
站在jvm的角度上,分为
引导类加载器(不是用java写的,是用c/c++),负责读取加载java中底层系统库
java写的类加载器(用来读取我们写的应用步伐)

在细分类加载器
1.启动类加载器
C/C++语言实现,负载加载java核心类库(系统库 java.lang)
2.扩展类类加载器
用java语言实现的,继承ClassLoader类,加载jre下面扩展类的 jre/lib/ext 子目录
3.应用步伐类加载器
用java语言实现的,继承ClassLoader类,用于加载用户本身界说的类(开发的应用步伐).

双亲委派机制

当加载一个类时,总是先让他的父级类加载器去加载,确保把系统中类优先加载,直到父类加载器找不到类时,再逐级向下,让子类加载器加载,
如果子级也找不到,终极抛出类找不到异常
为什么这样做?
防止我们本身写的类更换了系统中的类

如何打破双亲委派机制

自界说类加载器
  1. MyClassLoader extends ClassLoader
  2. //重写findClass()
复制代码


运行时数据区

存储运行时产生的各种数据
步伐计数器

步伐计数器用来记录每一个线程执行的指令位置,
速度是最快的,是线程私有的(每一个线程都会有一个步伐计数器)
此区域不会出现内存溢出,也不会垃圾接纳
虚拟机栈

栈是运行的,办理步伐方法执行,在虚拟机栈中,运行我们java本身写的方法
调用方法,方法入栈,运行结束出栈(先进后出 栈顶的方法,称为当前栈帧)
一个方法就是一个栈帧,在栈帧中存储局部变量,运行结果……
虚拟机栈也是线程私有的,线程之间相互隔离
栈区域不存在垃圾接纳,但是会存在内存溢出问题
栈帧中存储什么内容?
局部变量表 int a=10;
操作数栈(计算过程) int c = a+b;
方法返回地点
本地方法栈

本地方法栈是用来执行调用的本地方法的.
是线程私有的,不会存在垃圾接纳,
会出现内存溢出问题


堆概述

堆的作用是用来存储java语言产生的对象的.
是运行时数据区中最大的一块内存空间,空间大小可以设置
堆空间是所有线程共享的.
对空间是垃圾接纳的重点区域,堆中没有被使用到的垃圾对象,会被垃圾接纳器接纳调用
堆空间区域划分

堆分为
新生区(新生代 年轻代)
伊甸园区
幸存者0区
幸存者1区
老年区(老年代)
为什么分区(代)?

可以将不同生命周期的对象存储在不同的区域,针对不同的区域采用不同的垃圾接纳算法,使得垃圾接纳计谋更加优化.

对象创建存储过程

新创建的对象都存储在伊甸园区
当垃圾接纳时,将还被使用的对象,转移至某一个幸存者区,将伊甸园区举行清除,
当下一次垃圾接纳时,将伊甸园区存储的对象与当前正在使用的幸存者区存活的对象,转移至另一个幸存者区(每一次会空闲一个幸存者区)
当一个对象经历过15次垃圾接纳后,仍然存活的话,那么就把该对象移动到老年代,
老年代就比力少的举行垃圾接纳,在老年代空间不足时,对老年代会举行垃圾接纳,
当接纳后,内存仍然不足时,会触发FULL GC(整堆收集 应只管避免)
当整堆收集后仍然不敷使用,那么就会出现内存溢出错误 --OOM


jvm调优

可以根据步伐具体的使用场景,对运行时数据区的各种空间大小调解 例如堆,方法区
对垃圾接纳器举行选择(根据使用的场景选择单线程的或者是多线程的)

方法区

方法区主要用来存储加载的类 信息
方法区的大小也是可以设置的
方法区也会举行垃圾接纳,方法区也大概会出现内存溢出的问题
方法区的垃圾接纳

方法区的垃圾接纳,是对类信息举行接纳的
类信息如果不再被使用,类信息也可以被卸载
卸载条件

该类所产生的对象都不存在了
该类的Class对象,也不再被使用了
加载该类的类加载器也被接纳了.

本地方法接口

是虚拟机中专门用来调用本地方法的接口

什么是本地方法
在java中被native关键字修饰的方法,没有方法体,不是用java语言实现的方法,用C/C++在操作系统底层实现的方法
Object hashCode() 获取对象内存地点 涉及到读取内存
IO中读文件(输入文件 操作硬盘) read0();
启动线程 native void start0(); 启动线程 就是把这个线程注册到操作系统
java中为什么要调用本地方法
因为java属于应用层语言,有时间,需要对硬件系统资源举行调用
此时就不方便,再一个系统资源不答应应用层步伐直接调用
那么就需要通过本地方法 调用操作硬件资源

执行引擎

1.执行引擎是java虚拟机核心的组成部门之一
主要作用是将加载到虚拟机中的字节码,再次转换为机器码(字节码并不是系统可以或许直接执行的机器码)
执行引擎可以通过表明/编译两种方式 实现将字节码转为机器码
java步伐执行过程中涉及两次编译
第一次 .java(源代码 通过jdk javac 调用编译器) -->.class文件 称为前端编译
第二次 通过执行引擎 将字节码 编译为 机器码 称为后端编译

将字节码转为机器码有两种方式:
表明器(表明执行):对字节码逐行举行表明翻译,重复性的代码,也是每次都要表明执行,效率低
编译器(编译执行):对某一段字节码举行整体编译,然后存储起来,以后使用时不再需要编译了,效率高。
编译器会针对执行过程中的热点代码举行编译,并缓存起来

为什么要使用表明执行和编译执行并存这样的设计?
步伐开始运行时,表明器可以立即发挥作用,投入使用
而编译器固然执行效果高,但是前期需要对热点代码举行跟踪和编译,需要斲丧时间


垃圾接纳

什么是垃圾对象?
垃圾是指在运行步伐中没有任何引用指向的对象
就是一个对象 不再被任何的引用所指向。
没有任何引用所指向的对象
垃圾对象如果不清理,新的对象大概没有充足的空间,大概会导致内存的溢出问题。
垃圾接纳发展

早期c/c++这类语言,内存管理都是手动的,使用时申请,使用完后手动开释
优点:对内存管理更加精确,效率高
缺点:增长步伐员的负担,控制不好,容易出事(忘了开释,误操作内存空间)

后来发展为主动接纳:
java,,C#…都采用主动垃圾接纳
优点:解放了步伐员
缺点:会占用一些内存空间(垃圾不是出现后立即接纳的),降低了步伐员管理内存的本领
哪些区域会出现垃圾接纳?

堆 对象 频繁接纳年轻代 较少接纳老年代
方法区 类信息卸载 整堆收集时,会举行接纳 FULL GC

内存溢出与内存走漏

内存溢出:内存不敷用了
内存走漏:系统中那些用不到的,但是又不能接纳的对象
案例:单例对象
数据库连接对象,IO流,socket 这些提供close()类
用完之后,如果没有关闭, 垃圾接纳器是不能主动接纳这些对象的.
内存走漏,固然不能直接触发内存溢出,但是长期有对象不能被接纳,也是导致内存走漏的原因之一.

Stop the world

垃圾接纳时。会经历两个阶段:一是标记阶段 二是接纳阶段。
在标记和接纳时,需要我们的用户线程停息,不停息的话 在标记和接纳时大概会出现错标和漏标

垃圾接纳阶段算法

1.垃圾标记阶段

将虚拟机中不再被任何引用指向的对象标记出来,在垃圾接纳阶段,就会将标记出来对象举行接纳
垃圾标记阶段相关算法

引用计数算法(存在缺陷的,没有被虚拟机所使用的)
设计思想: 在对象中维护一个整数计数器变量 当有引用指向对象时,计数器就加一,相反就减一(引用断开)
优点: 设计实现简单,容易分辨对象是否是垃圾对象
缺点:需要维护一个变量存储引用数目,频繁修改引用计数器变量,占空间,还耗时
最重要的是,无法办理循环引用问题
可达性分析算法(根搜刮法)
设计思想:从一些可以被称为GCRoots的对象开始向下查找,只要某一个对象与GCRoots对象有接洽的,就可以判定对象是被使用的,与跟对象引用链没有任何关系的对象,可以视为垃圾对象
哪些对象可以作为GCRoots(根对象)?
1.虚拟机栈中(被调用的方法)所使用的对象
2.类中的静态属性
3.虚拟机中使用的系统类对象
4.所有被同步锁synchronized持有的对象


对象中的finalize机制

Object类中有一个finalize()这个方法是在对象被接纳之前,由虚拟机主动调用的,
在对象被接纳前,需要执行的一些操作,就可以在此方法中编写
finalize()方法可以在子类中重写
finalize()方法指挥被调用一次(第一次被判定为垃圾,要对其接纳,调用finalize(),对象有大概又被引用了,对象就不能被接纳,当下一次被判定为垃圾对象时,就不会调用finalize())

由于finalize()方法存在,被标记为垃圾的对象,也不是非死不可的。
可以将对象分为三种状态:
可触及:被GCRoots引用的, 不是垃圾对象
可复活的:被判定为垃圾的,但是finalize()方法还没有被调用过的
不可触及的(必死无疑的):被判定为垃圾,且执行过finalize()方法

2.垃圾接纳阶段

1.标记-复制算法

将内存可以分为多个较小的块,当发生垃圾接纳时,将一个区域中存活的对象复制到另一个区域,
在另一个区域从头开始排列,清除当前垃圾接纳的区域
优点:清理之后,内存没有碎片
不足:接纳时,需要移动对象,以是适合小内存块,而且存活对象少的环境
适合用于新生代
2.标记-清除算法

将被标记为垃圾的对象地点举行记录。后面如果分配新对象,判断垃圾对象空间能否存储下新的对象,
如果能存储下,用新对象直接覆盖垃圾对象即可
存活对象是不发生移动的.
优点:不会移动对象
不足:接纳后,内存空间碎片化
3.标记-压缩(整理)算法

将存活的对象会移动到内存区域的一端,按次序排列(压缩),清理边界以外的空间,在标记清除的底子上举行一次内存整理.
优点:接纳后没有内存碎片

标记-清除和标记压缩对比

标记-清除:不移动存活对象
标记-压缩:会移动存活对象
两者都适合用于老年代对象接纳
先使用标记-清除,当老年代 空间不足时,或者不能存储一个比力大的对象时,在使用标记-压缩算法

垃圾接纳时,根据不同的分区采用不同的接纳算法
新生代 : 标记-复制
老年代 : 标记-清除 标记-压缩

垃圾接纳器

什么是垃圾接纳器

垃圾接纳器,是对垃圾接纳过程实践者(落地)
不同的虚拟机中,垃圾接纳器种类也是很多的
有哪些垃圾接纳器 特点
垃圾接纳器分类:
从线程数目上分:
单线程 垃圾接纳线程只有一个
多线程 有多个垃圾接纳线程
从工作模式上分:
独占式:垃圾接纳线程执行时,其他用户线程需要停息(stop the world)
并发式: 垃圾接纳线程和用户线程可以做到并发执行
从分区角度上分:
新生代
老年代

垃圾收集器性能指标:

吞吐量
用户线程停息时间(重点)
接纳时内存开销
Serial 单线程 新生代
Serial Old, 单线程 老年代
ParNew、Parallel Scavenge, 多线程 新生代收集器
Parallel Old, 多线程老年代收集器
CMS, 多线程老年代收集器 (开创了垃圾收集线程与用户线程并发执行的先例)
并发标记清除 收集器
初始标记 --独占执行
并发标记 --并发执行
重新标记 --独占执行
并发清除 --并发执行
G1
G1垃圾接纳器,继承了CMS中,垃圾收集线程和用户线程并行执行的特点,减少了用户线程停息的时间
同时,将新生代和老年代的各个区域,又划分成更小的区域,对每个区域举行跟踪,
优先接纳代价高的区域(垃圾多的区域,例如可以把伊甸园区可以分成好几个小的区域)
提升接纳效率,进步了吞吐量,不再区分年轻代和老年代,可以做到对整个堆举行接纳。
非常适合服务器端步伐,大型项目
设置垃圾接纳器














免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

写过一篇

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表