数组边界检查消除因为Java会自动检查数组越界,每次数组元素的读写都带有一次隐含的条件判定操作,对于拥有大量数组访问的程序代码,这无疑是一种性能负担 。
如果数组访问发生在循环之中,并且使用循环变量来进行数组访问,如果编译器只要通过数据流分析就可以判定循环变量的取值范围永远在数组区间内 , 那么整个循环中就可以把数组的上下界检查消除掉,可以节省很多次的条件判断操作 。
方法内联内联消除了方法调用的成本,还为其他优化手段建立良好的基础 。
编译器在进行内联时,如果是非虚方法,那么直接内联 。如果遇到虚方法 , 则会查询当前程序下是否有多个目标版本可供选择,如果查询结果只有一个版本 , 那么也可以内联,不过这种内联属于激进优化,需要预留一个逃生门(Guard条件不成立时的Slow Path),称为守护内联 。
如果程序的后续执行过程中,虚拟机一直没有加载到会令这个方法的接受者的继承关系发现变化的类,那么内联优化的代码可以一直使用 。否则需要抛弃掉已经编译的代码 , 退回到解释状态执行,或者重新进行编译 。
逃逸分析逃逸分析的基本行为就是分析对象动态作用域:当一个对象在方法里面被定义后 , 它可能被外部方法所引用,这种行为被称为方法逃逸 。被外部线程访问到,被称为线程逃逸 。
如果对象不会逃逸到方法或线程外,可以做什么优化?
- 栈上分配:一般对象都是分配在Java堆中的,对于各个线程都是共享和可见的,只要持有这个对象的引用,就可以访问堆中存储的对象数据 。但是垃圾回收和整理都会耗时,如果一个对象不会逃逸出方法,可以让这个对象在栈上分配内存 , 对象所占用的内存空间就可以随着栈帧出栈而销毁 。如果能使用栈上分配,那大量的对象会随着方法的结束而自动销毁,垃圾回收的压力会小很多 。
- 同步消除:线程同步本身就是很耗时的过程 。如果逃逸分析能确定一个变量不会逃逸出线程 , 那这个变量的读写肯定就不会有竞争 , 同步措施就可以消除掉 。
- 标量替换:不创建这个对象,直接创建它的若干个被这个方法使用到的成员变量来替换 。
- 即时编译器运行占用的是用户程序的运行时间,具有很大的时间压力 。
- Java语言虽然没有virtual关键字,但是使用虚方法的频率远大于C++ , 所以即时编译器进行优化时难度要远远大于C++的静态优化编译器 。
- Java语言是可以动态扩展的语言,运行时加载新的类可能改变程序类型的继承关系,使得全局的优化难以进行 , 因为编译器无法看见程序的全貌,编译器不得不时刻注意并随着类型的变化,而在运行时撤销或重新进行一些优化 。
- Java语言对象的内存分配是在堆上,只有方法的局部变量才能在栈上分配 。C++的对象有多种内存分配方式 。
Java 内存模型什么是Java内存模型?Java虚拟机的规范 , 用来屏蔽掉各种硬件和操作系统的内存访问差异 , 以实现让Java程序在各个平台下都能达到一致的并发效果 。
Java内存模型的目标?定义程序中各个变量的访问规则,即在虚拟机中将变量存储到内存和从内存中取出这样的底层细节 。此处的变量包括实例字段、静态字段和构成数组对象的元素,但是不包括局部变量和方法参数,因为这些是线程私有的,不会被共享,所以不存在竞争问题 。
推荐阅读
- JVM学习笔记——垃圾回收篇
- 雾境序列荒林回响主线3
- 网吧怎么玩明日之后(网吧怎么登录明日之后pc)
- 低配电脑怎么玩明日之后(电脑如何玩明日之后)
- 【Java复健指南09】项目练习全解--房屋出租系统
- 【Bluetooth蓝牙开发】一、开篇词 | 打造全网最详细的Bluetooth开发教程
- 【Bluetooth|蓝牙开发】二、蓝牙开发入门
- 【深入浅出 Yarn 架构与实现】1-1 设计理念与基本架构
- 原神香醉坡兰那罗在哪
- 黑莓q5用安装微信的方法a 用黑莓自带的印象笔记手敲的 看不懂的宝宝们在私聊我吧