| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> Java知识库 -> JVM-类加载器 -> 正文阅读 |
|
[Java知识库]JVM-类加载器 |
目录 类加载的各个阶段一、加载将类的字节码载入方法区(1.8后为元空间,在本地内存中)中,内部采用 C++ 的 instanceKlass 描述 java 类,它的重要 ?eld 有:
如果这个类还有父类没有加载,先加载父类 加载和链接可能是交替运行的 ?二、连接1、验证
验证类是否符合 JVM规范,安全性检查。
用
UE
等支持二进制的编辑器修改
HelloWorld.class
的魔数,在控制台运行就会出现以下报错现象
2、准备
3、解析
将常量池中的符号引用解析为直接引用
一个未解析的类在常量池中会被标明未unresolvedClass,这种情况下是找不到他在内存中的地址的,也就是符号引用
当解析就不会被标记为unresolvedClass,并且能够找到他在内存中的地址 ? 三、初始化
初始化即调用 <cinit>()V ,虚拟机会保证这个类的『构造方法』的线程安全
类加载器
Bootstrap ClassLoader:先介绍一个jvm指令:-Xbootclasspath 表示定义启动类加载的路径
Extension ClassLoader?首先我自己创建了一个F类 ?然后这时候打包这个类为jar包,放入jdk/jre/lib/ext目录下 然后开始main方法,加载F类,可以看到是由拓展类类加载器进行加载的 ?双亲委派源码:
?过程
1.
sun.misc.Launcher$AppClassLoader
//1
处, 开始查看已加载的类,结果没有
2.
sun.misc.Launcher$AppClassLoader
// 2 处,委派上级sun.misc.Launcher$ExtClassLoader.loadClass()
3.
sun.misc.Launcher$ExtClassLoader
// 1
处,查看已加载的类,结果没有
4.
sun.misc.Launcher$ExtClassLoader
// 3
处,没有上级了,则委派
BootstrapClassLoader
查找
5.
BootstrapClassLoader
是在
JAVA_HOME/jre/lib
下找
H
这个类,显然没有
6.
sun.misc.Launcher$ExtClassLoader
// 4
处,调用自己的
fifindClass
方法,是在
JAVA_HOME/jre/lib/ext
下找
H
这个类,显然没有,回到
sun.misc.Launcher$AppClassLoader
的
// 2
处
7.
继续执行到
sun.misc.Launcher$AppClassLoader
// 4
处,调用它自己的
fifindClass
方法,在
classpath
下查找,找到了
自定义类加载器
步骤
自定义类加载器代码:
调用
即时编译器优化:对于java中的每一条指令,都会先通过虚拟机进行解释成机器码,然后再进行执行。但是如果对一些重复了很多次很多次的热点数据指令,一直在做重复的解释操作,无疑会耗费很多时间 JIT编译的交互过程:具体请参考 当一个方法被调用时,会先检查该方法是否存在被JIT 编译过的版本:如果存在,则优先使用编译后的本地代码来执行。如果不存在已被编译过的版本,则将此方法的调用计数器值加1,然后判断方法调用计数器与回边计数器值之和是否超过方法计数器的阈值。若超过了,则将会向即时编译器提交一个该方法的代码编译请求; 如果不做任何设置:执行引擎并不会同步等待编译请求完成,而是继续进入解释器按照解释方式执行字节码,直到提交的请求被编译器编译完成。当编译工作完成之后,这个方法的调用入口地址就会被系统自动改写成新的,下一次调用该方法时就会使用已变异的版本,整个JIT 编译的交互过程 具体包含以下几种优化 逃逸分析分析对象的动态作用域,当一个对象在方法中被定义后,它可能被外部方法所引用,例如作为调用参数传递给其他方法,称为方法逃逸。甚至还有可能被外部线程访问到,比如赋值给类变量或可以在其他线程中访问到的实例变量,称为线程逃逸。 优化方案 如果能证明一个对象不会逃逸到方法或线程之外,也就是别的方法或线程无法通过任何途径访问到这个对象,就可以为这个变量进行一些高效的优化:如:栈上分配、同步消除、标量替换等。
如果确定一个对象不会逃逸出方法之外,那让这个对象在栈上分配内存将是一个不错的主意,对象所占用的内存空间就可以随栈帧出栈而销毁;
线程同步本身是一个相对耗时的过程,如果逃逸分析能够确定一个变量不会逃逸出线程,那这个变量的读写肯定不会有竞争,对这个变量实施的同步措施就可以消除掉;
例如:
point方法并没有发生方法逃逸,那么就可以优化为:
方法内联对于一个方法的执行,会在线程的栈内存中压入栈帧内存,当方法执行完毕后又会将栈帧内存弹出,如果一个方法非常的简单,但是又重复多次执行(热点数据),也就是多次对栈帧的压栈和弹出,虚拟机认为有优化的空间,那么就直接将方法的内容直接放到调用的位置上,从而避免的压栈出栈的开销 例如:
优化为:
当启用方法内联的时候,如果在一个方法中多次使用一个成员变量,那么方法在读取成员变量的时候,会用一个局部变量来存储成员变量,这样再以后使用这个成员变量的时候只需要再本地查找局部变量就可以 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 3:22:11- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |