JVM简单学习

jvm与字节码

jvm只需关注字节码文件
在这里插入图片描述
jvm由哪些部分构成
在这里插入图片描述
1.类加载子系统,将磁盘中的字节码文件加载到方法区的内存空间中
在这里插入图片描述
类加载器分两种:引导类加载器是jvm底层中用C和C++语言写的

在这里插入图片描述
各个默认的类加载器的不同区别在于 各自默认负责要加载的类的目录不一样
比如
BootStrapClassLoader:负责jre/lib 目录下
ExtClassLoader:负责jre/lib/ext 目录下
AppClassLoader:负责 classpath目录下

什么是双亲委派 和 双亲委派的两大作用

  1. 避免类的重复加载
  2. 防止核心API被篡改

什么是双亲委派机制

双亲委派机制(Parent Delegation Mechanism)是Java中的一种类加载机制。在Java中,类加载器负责加载类的字节码并创建对应的Class对象。双亲委派机制是指当一个类加载器收到类加载请求时,它会先将该请求委派给它的父类加载器去尝试加载。只有当父类加载器无法加载该类时,子类加载器才会尝试加载。

这种机制的设计目的是为了保证类的加载是有序的,避免重复加载同一个类。Java中的类加载器形成了一个层次结构,根加载器(Bootstrap ClassLoader)位于最顶层,它负责加载Java核心类库。其他加载器如扩展类加载器(Extension ClassLoader)和应用程序类加载器(Application ClassLoader)都有各自的加载范围和职责。通过双亲委派机制,可以确保类在被加载时,先从上层的加载器开始查找,逐级向下,直到找到所需的类或者无法找到为止。

这种机制的好处是可以避免类的重复加载,提高了类加载的效率和安全性。同时,它也为Java提供了一种扩展机制,允许开发人员自定义类加载器,实现特定的加载策略。

双亲委派机制的原理

双亲委派机制是Java中的一种类加载机制。其原理如下:

  1. 当Java程序需要加载一个类时,首先会委托给当前类加载器的父类加载器进行加载。

  2. 父类加载器会按照相同的方式尝试加载该类。如果父类加载器能够成功加载该类,则加载过程结束。

  3. 如果父类加载器无法加载该类,则会将加载请求再次委托给它的父类加载器,直到达到顶层的引导类加载器。

  4. 引导类加载器是Java虚拟机内置的类加载器,它负责加载核心类库,如java.lang包下的类。

  5. 如果引导类加载器也无法加载该类,则会回到初始的类加载器,尝试使用自身的加载机制加载该类。

  6. 如果自身的加载机制仍然无法加载该类,则会抛出ClassNotFoundException异常。

通过这种双亲委派的机制,Java实现了类加载的层次结构。它可以确保类的加载是有序的,避免了重复加载和类的冲突。同时,它也提供了一种安全机制,防止恶意代码的加载和执行。

主要实现在ClassLoader里的loadClass方法

双亲委派主要体现在 ClassLoader#loadClass() 方法中:

PS:每个 ClassLoader 都有如下三个基础方法:

  • loadClass()
    • 入口,定义了 加载/寻找 Class 的策略。比如双亲委派,或者其他形式
    • 调用 findClass() 读入 class 文件,并生成 Class 对象
  • findClass()
    • 根据 class 名,在当前 ClassLoader 能处理路径中查找,如果能找到就将 class 文件读入
    • 调用 defineClass 生成 Class 对象
  • defineClass()
    • native 方法
    • 将字节数组生成 Class 对象
// resolve = false 不进行解析
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException{synchronized (getClassLoadingLock(name)) {// 查看该类是否被加载过Class<?> c = findLoadedClass(name);if (c == null) {long t0 = System.nanoTime();try {// 获取当前类父类的加载器if (parent != null) {// 使用父类的加载器加载!!!// 递归c = parent.loadClass(name, false);} else {// 如果 parent 为 null,说明父类加载器为引导类加载器c = findBootstrapClassOrNull(name);}} catch (ClassNotFoundException e) {}// 当前类的加载器父类加载器未加载此类 or 当前类的加载器未加载此类if (c == null) {long t1 = System.nanoTime();// 调用当前 Classloader 的 findClass// 注:可能当前 classloader 无法处理要加载的这个类的路径,这时返回 nullc = findClass(name);// this is the defining class loader; record the statssun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);sun.misc.PerfCounter.getFindClasses().increment();}}// 根据入参决定是否解析if (resolve) { resolveClass(c);}return c;}
}

如何自定义类加载器,下面是一个自定义 ClassLoader 示例,直接继承 ClassLoader 类,然后重写 findClass 方法就行了(采用双亲委派)

public class MyClassLoader extends ClassLoader{// 指定的要加载 class 文件的目录private File classPathFile;  public MyClassLoader(String absolutePath) {this.classPathFile = new File(absolutePath);}@Override// 根据类名将指定类加载进 JVM// 注:该 class 必修在指定的 absolutePath 下protected Class<?> findClass(String name) throws ClassNotFoundException {// 拼接全类名String className = MyClassLoader.class.getPackage().getName() + "." + name;if(classPathFile  != null){// 根据绝对路径,以及 class 文件名,拿到 class 文件// 注意全类名的情况 File classFile = new File(classPathFile,name.replaceAll("\\.","/") + ".class");// 如果 class 文件存在if(classFile.exists()){// 将 class 文件读入内存,暂存到一个字节数组中FileInputStream in = null;ByteArrayOutputStream out = null;try{in = new FileInputStream(classFile);out = new ByteArrayOutputStream();byte [] buff = new byte[1024];int len;while ((len = in.read(buff)) != -1){out.write(buff,0,len);}// 构造类的 Class 对象!!!// 注:defineClass() 是一个 native 方法return defineClass(className, out.toByteArray(), 0, out.size());}catch (Exception e){e.printStackTrace();}}}return null;}
}

运行时数据区

在这里插入图片描述

程序计数器

在这里插入图片描述

Java方法栈

一个方法对应一个栈帧,方法内有其他方法就会依次入栈,执行完的方法对应的栈帧会出栈

在这里插入图片描述
OOM是内存不够, StackOverflowError 是方法调用层次太多
在这里插入图片描述

栈帧

局部变量表

slot 代表各个方法内的局部变量
在这里插入图片描述

操作数栈

在这里插入图片描述

在这里插入图片描述
执行步骤

  • 10 压入操作数栈
  • 将 10 放入局部变量表 2
  • 将20 压入操作数栈
  • 将20 放入局部变量表2
  • iload1 将 局部变量表1放入操作数栈 iload2 将 局部变量表2放入操作数栈
  • iadd 操作数栈中相加,得到的值放入局部变量3
    在这里插入图片描述

本地方法栈

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
Java对象在各个区域的流转情况

对象首先来到Eden区,Eden满了后进行一次GC,没被清理的对象来到S0区计数加一,Eden迎接新对象,每次GC存活对象计数加一,计数达到阈值进入老年代,如果有大对象(文件上传对象)S0和S1放不下直接进入老年代
在这里插入图片描述

各个GC的区别

老年代只有一个CMS专门回收
在这里插入图片描述

为什么要进行垃圾回收

在这里插入图片描述

垃圾标记阶段,如何标记垃圾

在这里插入图片描述

引用计数法

在这里插入图片描述

可达性分析法

在这里插入图片描述

GCRoots包括哪些

在这里插入图片描述
虚拟机栈和本地方法栈中的方法参数和局部变量存储的是对象的地址值

GC算法

标记清除算法

在这里插入图片描述

  • 缺点
    • 效率不高
    • 会产生内存碎片
  • 优点
    • 简单
复制算法

利用空间换时间,适合垃圾对象比较多,非垃圾对象少,这样复制成本就低效率就高。
新生代适合用复制算法,因为对象朝生夕死

在这里插入图片描述
在这里插入图片描述

标记整理算法

在这里插入图片描述
在这里插入图片描述

算法总结

在这里插入图片描述

一种GC算法的使用理念

算法按需使用,用到最适合他的地方

在这里插入图片描述

常见的垃圾收集器

在这里插入图片描述

CMS 如何工作

在这里插入图片描述

并发标记清除算法,特点低暂停,STW时间短,执行过程长,工作线程暂停时间短影响小,所以用户体验好,但是吞吐量变低
在这里插入图片描述

  • 阶段一 初始标记:

    • STW暂停所有工作线程
    • 标记出GCRoots能直接可达对象(以GCRoots为起点的第一层引用对象,不再向下标记)
    • 一旦标记,就回复工作线程继续执行
    • 这个阶段比较短,所以STW时间短
  • 阶段二 并发标记(最费时的阶段,但是不STW不影响工作线程工作):
    在这里插入图片描述
    因为工作线程也在运行中,标记垃圾可能会有误差,因为程序在运行就有可能产生垃圾对象,但是误差不大

  • 阶段三和阶段四 重新标记短暂STW后并发清理
    在这里插入图片描述

CMS存在的问题

在这里插入图片描述

G1是如何工作的

在这里插入图片描述

G1垃圾回收器下,堆空间不再是其他回收器那样的各个代之间层次分明,而是把堆空间分成2048个Region进行管理,各个代空间逻辑上连续,但是物理上不再连续

在这里插入图片描述
G1的初始标记和并发标记与CMS相同

在这里插入图片描述

G1和CMS最大区别在最后一步,CMS是清除算法,G1是复制算法,复制到空闲的region
在这里插入图片描述

G1的筛选回收

可以指定GC的STW停顿时间,CMS的STW时间是不确定的,相较于CMS的清除算法,G1是把需要清理的Region中的非垃圾对象复制到空闲的Region区域

在这里插入图片描述

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/351380.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

谈一谈自己对依赖、关联、聚合和组合之间区别的理解

在学习面向对象设计对象关系时&#xff0c;依赖、关联、聚合和组合这四种关系之间区别比较容易混淆。特别是后三种&#xff0c;仅仅是在语义上有所区别&#xff0c;所谓语义就是指上下文环境、特定情景等。他们在编程语言中的体现却是基本相同的&#xff0c;但是基本相同并不等…

Java Bullshifier –生成大量随机代码库

生成大量随机Java应用程序的命令行工具 您一直在等待的命令行工具。 或不。 毕竟&#xff0c;这是很深奥的。 无论哪种方式&#xff0c;它对某些人都非常有用&#xff0c;而对其他人来说却是一个有趣的实用程序。 Bullshifier是由David Levanon和Hodaya Gamliel开发的内部Over…

二级c语言光盘,二级c语言(光盘).doc

1程序设计题&#xff1a; 请编写一个函数 unsigned fun (unsigned w ) w是一个大于10的无符号整数。例如&#xff1a;W值为5923&#xff0c;则函数返回923&#xff1b;W值为923&#xff0c;则函数返回23。if ( w >10000 ) w % 10000 ; 程序修改题: m i; 和 if( a[k]>a[m]…

设计模式六大原则(3):依赖倒置原则

定义&#xff1a; 高层模块不应该依赖低层模块&#xff0c;二者都应该依赖其抽象&#xff1b;抽象不应该依赖细节&#xff1b;细节应该依赖抽象。 问题由来&#xff1a;类A直接依赖类B&#xff0c;假如要将类A改为依赖类C&#xff0c;则必须通过修改类A的代码来达成。这种场景下…

Jirasearch 2.0狗粮:使用Lucene查找我们的Jira问题

几年前&#xff0c;我首先构建并发布了Jirasearch &#xff0c;它是用于薄型包装Lucene服务器的有趣的狗粮测试用例&#xff0c;以针对我们的Jira问题公开强大的搜索UI。 这很好地展示了Lucene的许多重要功能&#xff1a; 使用块联接查询来建模父文档&#xff08;原始的Jira问…

Highcharts教程--把js代码从html中抽离出来,放到单独的一个js文件中。由html页面调用...

1.html页面写法 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>第一个 Highcharts 图表</title><!-- 引入 jquery.js --><script src"static/jquery-3.3.1.min.js"><…

数据结构c语言版第16页,数据结构c语言版

数据结构c语言版[编辑]概述《数据结构C语言版》本书的前半部分从抽象数据类型的角度讨论各种基本类型的数据结构及其应用;后半部分主要讨论查找和排序的各种实现方法及综合分析比较出版信息作/译者&#xff1a;严蔚敏&#xff0c;吴伟民 出版社&#xff1a;清华大学出版社出版日…

C语言申请内存时堆栈大小限制

一直都有一个疑问&#xff0c;一个进程可以使用多大的内存空间&#xff0c;swap交换空间以及物理内存的大小&#xff0c;ulimit的stack size对进程的内存使用有怎样的限制&#xff1f;今天特亲自动手实验了一次&#xff0c;总结如下&#xff1a; 开辟一片内存空间有2种方式&…

微服务之数据同步Porter

Porter是一款数据同步中间件&#xff0c;主要用于解决同构/异构数据库之间的表级别数据同步问题。 背景 在微服务架构模式下深刻的影响了应用和数据库之间的关系&#xff0c;不像传统多个服务共享一个数据库&#xff0c;微服务架构下每个服务都要有自己的数据库。如果你想获得微…

C语言采用多文件的工程结构百度,C语言学习知识复习资料结构框架学习知识重点.doc...

C语言学习知识复习资料结构框架学习知识重点.doc .思维导图1C语言程序设计知识结构第一课 C语言程序设计基础思维导图2第一课 C语言程序设计基础本课主要知识点1.知识点C程序基础l C语言是一种结构化程序设计语言。三种基本结构顺序、选择、循环。例1(2010-09-11)以下关于结构化…

antlr_ANTLR –语义谓词

antlr用antlr解析简单的语法很简单 。 您要做的就是使用正则表达式描述您的语言&#xff0c;并让antlr生成词法分析器和解析器。 解析大型或复杂的语言有时会需要更多&#xff0c;因为仅使用正则表达式描述它们是困难的&#xff0c;甚至是不可能的。 语义谓词是在语法内部编写…

栈大小和内存分部问题

今天面试问了一个栈大小问题&#xff0c;问过两次内存的结构问题&#xff0c;都没有答好&#xff0c;这次要弄清楚才行。 栈大小是有默认值的&#xff0c;如果申请的临时变量太大的话就会超过栈大小&#xff0c;造成栈溢出。 编译期限制栈大小&#xff0c;和系统限制栈深度根本…

ssh登陆报错“WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!”的解决方法

解决方法&#xff1a;删除 ~/.ssh/known_hosts转载于:https://www.cnblogs.com/liangxc/p/10414123.html

android 动态修改菜单,如何在Android的“选项”菜单上更改MenuItem?

如何在Android的“选项”菜单上更改MenuItem&#xff1f;我的Activity上有一个选项菜单&#xff0c;带有mymenu.xml“开始”。 选择此3000128611611048489985后&#xff0c;我想更改菜单&#xff0c;使其包含MenuItem“停止”。 最后&#xff0c;当选择“停止”时&#xff0c;我…

Java性能监控:您应该了解的5个开源工具

鲜为人知但有用&#xff1a;开源应用程序性能监视的状态 对于任何应用程序来说&#xff0c;最重要的事情之一就是性能。 我们要确保用户获得他们能获得的最佳体验&#xff0c;并且要知道我们的应用已启动并正在运行。 这就是为什么我们大多数人至少使用一种监视工具的原因。 …

【BZOJ1069】【SCOI2007】—最大土地面积(凸包+旋转卡壳)

传送门 考虑枚举任意222个点&#xff0c;那么只需要枚举第二个点的时候旋转卡壳就可以O(n)O(n)O(n)得到最远点对了 #include<bits/stdc.h> using namespace std; inline int read(){char chgetchar();int res0,f1;while(!isdigit(ch)){if(ch-)f-f;chgetchar();}while(isd…

如何在vs2010中修改栈的大小

上次运行程序的时候提示栈溢出&#xff0c;oh,my god 程序栈空间不够用了&#xff0c;没关系&#xff0c;可以设置栈的大小&#xff0c;默认是1MB。 选择 项目->属性->链接器->系统->堆栈保留大小,然后输入你想要的栈大小即可。

android第三方登录appid,AndroidQQ第三方登录

集成QQ登录在lib导入该open_sdk_r5886_lite.jar包AndroidManifest.xmlandroid:name"com.tencent.tauth.AuthActivity"android:launchMode"singleTask"android:noHistory"true" >android:theme"android:style/Theme.Translucent.NoTitleB…

Java数组、集合的三种遍历方式(包懂)

1 for循环 for(int i 0;i<arr.length;i){System.out.print(arr[i]" "); } 2 foreach循环&#xff0c;这种方式结构简单&#xff0c;可以简化代码 for(int i:arr){System.out.print(arr[i]" "); } 3 迭代器遍历 对于数组而言&#xff0c;就没必要转换为…

你应当如何学习C++(以及编程)(rev#1)

你应当如何学习C(以及编程)(rev#1) By 刘未鹏(pongba) C的罗浮宫(http://blog.csdn.net/pongba) JavaScript是世界上最受误解的语言&#xff0c;其实C何尝不是。坊间流传的错误的C学习方法一抓就是一大把。我自己在学习C的过程中也走了许多弯路&#xff0c;浪费了不少时间。 为…