java 执行机制_Java类的执行机制

在完成将class文件信息加载到JVM并产生Class对象后,就可执行Class对象的静态方法或实例化对象进行调用了。在源码编译阶段将源码编译为JVM字节码,JVM字节码是一种中间代码的方式,要由JVM在运行期对其进行解释并执行,这种方式成为字节码解释执行方式

字节码解释执行

由于采用的为中间码的方式,JVM有一套自己的指令,对于面向对象的语言而言,最重要的是执行方法的指令,JVM采用了invokestatic、invokevirtual、invokeinterface、invokespecial四个指令来执行不同的方法调用。invokestatic对应的是调用static方法,invokevirtual对应的是调用对象实例的方法,invokeinterface对应的是调用接口的方法,invokespecial对应的是调用private方法和编译源码后生成的方法,此方法为对象实例化时的初始化方法(构造方法)。

Sun

JDK基于栈的体系结构来执行字节码,基于栈方式的好处是代码紧凑,体积小。线程在创建后,都会产生程序计数器(PC)和栈(Stack):PC存放了下一条要执行的指令在方法内的偏移量,栈中存放了栈帧,每个方法每次调用都会产生栈帧。栈帧主要分为局部变量区和操作数栈两部分,局部变量区用于存放方法中的局部变量和参数,操作数栈中用于存放方法执行过程中产生的中间结果,栈帧中还会有一些杂用空间,例如指向方法已解析的常量池的引用、其他一些VM内部实现需要的数据等。

a4c26d1e5885305701be709a3d33442f.png

1、指令解释执行

对于方法的指令解释执行,执行方式为经典冯诺依曼体系中的FDX循环方法,即获取下一条指令,解码并分派,然后执行。在实现FDX循环式有switch-threading、token-threading、direct-threading、subroutine-threading、inline-threading等多种方式。Sun

JDK的重点为编译成机器码,并没有在解释器上做太复杂的处理,因此采用了token-threading方式。为了让解释执行能更加高效,Sun

JDK还做了一些其他的优化,主要有:栈顶缓存和部分栈帧共享。

2、栈顶缓存

在方法的执行过程中,可看到有很多操作要将值放入操作数栈,这导致了寄存器和内存要不断的交换数据,Sun

JDK采用了一个栈顶缓存,即将本来位于操作数栈的值直接缓存在寄存器上,这对于大部分只需要一个值的操作而言,无需将数据放入操作数栈,可直接在寄存器计算,然后放回操作数栈。

3、部分栈帧共享

当一个方法调用另一个方法时,通常传入另一个方法的参数为已存放在操作数栈的数据,Sun

JDK在此做了一个优化,就是当调用方法时,后一方法可将前一方法的操作数栈作为当前方法的局部变量,从而节省数据copy带来的消耗。

编译执行

编译执行的效率较低,为提升代码的执行性能,SunJDK提供将字节码编译为机器码的支持,编译在运行时进行,通常称为JIT编译器。SunJDK在执行过程中对执行频率高的代码进行编译,对执行不频繁的代码则继续采用解释执行的方式,因此SunJDK又称为Hotspot

VM,在编译上SunJDK提供了两种模式client compiler(-client)和server

compiler(-server)。

client

compliler又称为C1,较为轻量级,只做少量性能开销比高的优化,它占用内存较少,适合桌面交互式应用,在寄存器分配策略上,JDK6以后采用的为线性扫描寄存器分配算法,在其他方面的优化主要有:方法内嵌、去虚拟化、冗余消除等。

1、方法内联

对于java面向对象的语言,通常要调用多个方法来完成功能,执行时,要经历多次参数传递,返回值传递及跳转等,于是C1采用了方法内联的方式,即把调用到的方法的指令直接植入到当前的方法中。(可在debug版本的JDK的启动参数加速-XX:PrintInlining来查看方法内联的信息)

2、去虚拟化

去虚拟化是指在装载class文件后,进行类层次的分析,如发现类中的方法只提供一个实现类,那么对于调用此方法的代码,也可进行方法内联,从而提升执行的性能。

3、冗余消除

冗余消除是指在编译时,根据运行时状况进行代码折叠或消除。如某个判断条件为false则可将条件内的代码消除。

Server

Compiler又称为C2,较为重量级,C2采用了大量传统编译优化技巧,占用内存会相对多,适用于服务器应用。和C1不同的主要是寄存器分配策略和优化的范围,寄存器分配策略上C2采用的为传统的图着色寄存器分配算法:由于C2会收集程序的运行信息(收集的信息主要有,分支的跳转/不跳转的频率,某条指令出新过的类型、是否出现过控制、是否出现过一场),因此其优化的范围更多在于全局的优化,而不仅仅是一个方法块的优化。

逃逸分析是C2进行很多优化的基础,逃逸分析是指根据运行状况来判断方法中的变量是否会被外部读取,如不会则认为此变量是逃逸的,基于逃逸分析C2在编译时会做标量替换、栈上分配和同步消除等优化。

1、标量替换

变量替换的意思简单来说就是用标量替换聚合量。这种方式能带来的好处是,如果创建的对象并未用到其中的全部变量,则可以节省一定的内存。

2、栈上分配

如果变量没有逃逸,那么C2会选择在栈上直接创建对象实例,而不是在JVM堆上,在栈上分配的好处一方面是更加快速,另一方面是回收时随着方法的结束,对象也被回收了。

3、同步消除

同步消除是指如果发现同步的对象未逃逸,那也没有同步的必要了,在C2编译时会直接去掉同步。

除了C1\C2外,还有一种较为特殊的编译:OSR(On

Stack

Replace)。OSR和C1、C2的最主要的不同点在于OSR编译只替换循环代码体的入口,而C1、C2替换的是方法调用的入口,因此在OSR编译后会出现的现象是方法的整段代码都被编译了,但在只有循环代码体部分才执行编译后的机器码,其他部分仍然是是解释执行方法。

默认情况下,SunJDK根据机器配置来选择C1或C2模式,当机器配置CPU超过2核且内存超过2GB及默认为C2模式,但在32位机器上时钟选择的都是C1模式,也可在启动时通过增加-client或-server来强制指定。

SunJDK为提升程序执行性能,在C1好C2上做了很多努力,其他各种实现的JVM也在编译执行上做了很多的优化,SunJDK之所以未选择在启动时即编译成机器码,主要是因为:静态编译并不能根据程序的运行状况来优化执行的代码,C2这种方式是根据运行状况来进行动态编译的,如分支判断、逃逸分析等,这些措施会提升程序执行的性能,在静态编译的情况下是无法实现的,给C2收集运行数据越长时间,编译出的代码也会越优;解释执行比编译执行更节省内存;启动时解释执行的启动速度比编译在启动更快。

当程序在未编译期间解释执行会比较慢,因此需要取一个权衡值,在SunJDK中主要依据方法上的两个计数器是否超过阈值,其中一个计数器为调用计数器,即方法被调用的次数;另一个为回边计数器,即方法中循环执行部分代码的执行次数。下面介绍两个计数器对应的阈值

(1)ComplieThresold

该值是指方法被调用多少次后,就编译为机器码,在client模式下默认为1500次,在server模式下为10000次,可通过在启动时天机-XX:CompilerThreshold=10000来设置该值

(2)OnStackReplacePercentage

该值用于计算是否触发OSR编译的阈值,默认模式下client为933,server模式下为140,该值可通过在启动时添加-XX:OnStackReplacePercetage=140来设置。

反射执行

反射执行是Java的亮点之一,基于反射可动态调用某对象实例中对应的方法、访问查看对象的属性等,无需再编写代码时就确定要创建的对象。这使得Java可以很灵活的实现对象的调用,例如MVC框架中通常要调用实现类中的execute方法,但框架在编写时是无法知道实现类的,在Java中则可以通过反射机制直接去调用应用类的实现类中的execute方法。

这种方式对于框架之类的代码而言非常重要,反射和直接创建对象实例调用方法的最大不同在于创建的过程、方法调用的过程是动态的。这也是的采用反射生成执行方法调用的代码并不像直接调用实例对象代码,编译后就可直接生成对象方法调用的字节码,而是只能生成调用JVM反射实现的字节码了。

要实现动态的调用,最直接的方法就是动态生成字节码,并加载到JVM中执行,SunJDK采用的即为这种方法。

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

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

相关文章

论如何入门地使用vscode

微软大法好啊 这货更像是个gedit 以下内容只适合Oiers使用 本文档只适合新手引导的阶段使用 下载 这个是链接 可见这东西是和Emacs一样跨系统的 不知道为什么下载速度贼快 配置 还记得我们用Emacs的时候配置那叫一个可怕 虽然使用vscode也要配置 不过我们在配置它的时候就比Ema…

springboot jpa 创建数据库以及rabbitMQ分模块扫描问题

在使用jpa过程中,如果没有在配置中加入自动创建实体对于的sql,则需要提前创建建表语句 spring.jpa.properties.hibernate.show_sqltrue spring.jpa.properties.hibernate.format_sqltrue spring.jpa.hibernate.ddl-autoupdate 建表语句需要注意的点:需要…

cpp_06_缺省构造_拷贝构造_拷贝赋值_初始化表

1 构造函数 1.1 构造函数可重载&#xff1a; 构造函数可以通过形参表的差别化形成重载关系 重载关系的构造函数&#xff0c;通过构造函数的实参类型进行匹配 使用缺省参数可以减少构造函数重载的数量 // consover.cpp 构造函数的重载 #include <iostream> using name…

mysql sumif条件求和_sumif与sumifs条件求和函数详解,小白到大神的必经之路

在日常工作中我们经常需要根据某些条件进行求和&#xff0c;今天就给大家介绍下&#xff0c;Excel中的条件求和函数sumif和sumifsSumif函数第一个参数&#xff1a;Range&#xff1a;条件区域&#xff0c;用于条件判断的单元格区域。第二个参数&#xff1a;Criteria&#xff1a;…

Thread.join(), CountDownLatch、CyclicBarrier和 Semaphore区别,联系及应用

在java 1.5中&#xff0c;提供了一些非常有用的辅助类来帮助我们进行并发编程&#xff0c;比如CountDownLatch&#xff0c;CyclicBarrier和Semaphore&#xff0c;今天我们就来学习一下这三个辅助类的用法&#xff0c; 由于Thread.join()也和这三个类有类似用法&#xff0c;我也…

string转short java_[Java基础]之 数据类型转换

数据类型转换存在的意义数据类型转换&#xff0c;在实际的应用开发中&#xff0c;常常会对不同类型的数字类型进行计算&#xff0c;所以就用到了数据转换。一方面&#xff0c;使用算术计算符对数字进行运算时&#xff0c;系统在适当的时候回进行自动转换&#xff1b;另一放方面…

IDEA建立Spring MVC Hello World 详细入门教程

引子&#xff0c;其实从.NET转Java已经有几个月时间了&#xff0c;项目也做了不少&#xff0c;但是很多配置都是根据公司模板或者网上教程比忽略画瓢&#xff0c;对其中最简单的配置和设置并不完全理解&#xff0c;依旧是小白用户。最近项目不忙&#xff0c;重新梳理了一下Spri…

2048小游戏代码解析 C语言版

2048小游戏&#xff0c;也算是风靡一时的益智游戏。其背后实现的逻辑比较简单&#xff0c;代码量不算多&#xff0c;而且趣味性强&#xff0c;适合作为有语言基础的童鞋来加强编程训练。本篇分析2048小游戏的C语言实现代码。 前言 游戏截图&#xff1a; 游戏实现原理&#xff1…

【递归与递推】青蛙过河

题目描述 有一条河&#xff0c;左边一个石墩(A区)上有编号为1&#xff0c;2&#xff0c;3&#xff0c;4&#xff0c;…&#xff0c;n的n只青蛙&#xff0c;河中有k个荷叶(C区)&#xff0c;还有h个石墩(D区)&#xff0c;右边有一个石墩(B区)&#xff0c;如下图2—5所示。n只青蛙…

python arp欺骗

使用python构造一个arp欺骗脚本 import os import sys from scapy.all import * import optparse def main():usage"usage:[-i interface] [-t IP to attack] [-g Gateway IP]"parseroptparse.OptionParser(usage)parser.add_option(-i,destinterface,helpselect int…

java对外sdk提供接口_Android SDK封装,对外提供接口

项目中需要把连接服务器的部分做成一个service并生成一个jar模块。其他产品就可通过这个包来快速的开发连接服务器的应用软件。做成一个service的优点是&#xff1a;1&#xff0e; 在后台运行&#xff0c;可以一直保持与服务器的连接2&#xff0e; 服务可以只对外提供接口&…

hdu3265一种错误的做法

题目链接 这是求面积并的题目&#xff0c;刚开始我的思路是将挖去的矩形的入边和出边覆盖效果颠倒&#xff0c; 即入边-1&#xff0c;出边1&#xff0c;后来调试到爆炸&#xff0c;发现这是错误的做法。。原因就是对最简单 的面积并问题没有搞清楚。刚开始接触扫描线的时候我就…

php截断上传,截断在文件包含和上传中的利用

截断大概可以在以下情况适用include(require)file_get_contentsfile_exists所有url中参数可以用%00控制0x01. 本地文件包含1.1 截断类型&#xff1a;php %00截断截断条件&#xff1a;php版本小于5.3.4 详情关注CVE-2006-7243php的magic_quotes_gpc为OFF状态漏洞文件lfi.php要in…

解决虚拟机安装64位系统“此主机支持 Intel VT-x,但 Intel VT-x 处于禁用状态”的问题...

环境说明&#xff1a;系统&#xff1a;Windows 8.1 简体中文专业版 虚拟机&#xff1a;VMware Workstation 11.0.0 报错&#xff1a;此主机支持 Intel VT-x&#xff0c;但 Intel VT-x 处于禁用状态。如图&#xff1a; 图片原文如下&#xff1a; 已将该…

#前端# 解决前端页面滑动不顺畅的问题

看情况有时候需要将body和html同时选择。转载于:https://www.cnblogs.com/tnt-33/p/8464370.html

php守护进程热更新,如何通过PHPStorm配置Hyperf热更新开发环境

通过 PHPStorm 配置热更新开发环境在开发 Hyperf/Swoole 这样的持久化应用时&#xff0c;每当应用代码发生了变更时&#xff0c;都需要重启应用使代码生效&#xff0c;尽管在开发 CLI 应用时这也是一个正确且合理地操作&#xff0c;因为我们开发过程中仍需要关注 stdout 输出的…

php elements,wd elements se和wd elements的区别是什么

区别&#xff1a;1、WD Elements SE有两个USB3.0接口&#xff1b;而WD Elements有一个USB3.0接口&#xff0c;一个USB2.0接口。2、WD Elements SE配置有数据加密功能&#xff1b;而WD Elements不具备存储数据加密功能。本文操作环境&#xff1a;windows10系统、thinkpad t480电…

【热修复】Andfix源码分析

转载请标注来源&#xff1a;http://www.cnblogs.com/charles04/p/8471301.html Andfix源码分析 0、目录 背景介绍源码分析方案评价总结与思考参考文献1、背景介绍 热修复技术是移动端领域近年非常活跃的一项新技术&#xff0c;通过热修复技术可以在不发布应用市场版本&#xff…

已知矩阵 matlab,在MATLAB中,已知矩阵A,那么A(:,2:end)表示

摘要&#xff1a;已知供输工方、表示添资料准加剂、加及标应提原料有关的()的出国法等使用&#xff0c;品”“进办理报检时口食。已知信息系统模型不包逻辑括(。...已知信息系统构化中的结方法设计&#xff0c;矩阵细设和详总体计两阶段一般分为设计&#xff0c;总体主要建立其…

文件源码读取 php伪协议,include(文件包含漏洞,php伪协议)

点击tips查看元素&#xff0c;也并没有有用的信息&#xff0c;联想到题目,include想起了文件包含漏洞。构造payload?file/../../../../../../flag.php没有返回东西。看完wq学到了一个新姿势&#xff1a;php伪代码构造payload?filephp://filter/readconvert.base64-encode/res…