JVM详解之:HotSpot VM中的Intrinsic methods
简介
内置方法是什么呢?它和inline method有什么关系呢?内置方法是怎么实现的呢?所有的问题都可以在本文找到答案。
什么是Intrinsic Methods
什么是内置方法呢?
维基百科给出的定义是这样的:
在计算机软件中,按照编译器理论,固有方法(或内置方法)是可在给定编程语言中使用的方法,该编程语言的实现由编译器专门处理。通常,它可以将自动生成的指令序列替换为原始方法调用,类似于内联方法。与内联方法不同,编译器对内置方法有深入的了解,因此可以针对给定情况更好地集成和优化它。
实现内置方法的编译器通常仅在程序请求优化时才启用它们,否则会退回到语言运行时环境提供的默认实现。
所以总结一下,内置方法就是编译器内置的方法实现。
内置方法的特点
内置方法有什么特点呢?我们在这里总结一下。
多样性
因为内置方法是在编译器内部实现的,所以不同的虚拟机,其内置方法是不一样的。
我们不能直接说哪个方法是内置方法,因为不同的JVM是不同的。
兼容性
内置方法是在需要的时候才会使用的,如果在不需要的时候则会回退到普通的方法实现,也就是java代码的实现。
所以在java源代码级别来看,内置方法和非内置方法是一样的。他们的区别在于JVM的实现。
java语义的扩展
有些方法用普通的java代码是无法实现的。比如sun.misc.Unsafe.compareAndSwapInt()。
我们只能使用JNI或者内置方法来对其实现。所以内置方法可以实现对java语义的扩展。
一般来说,JDK和核心库中,能使用内置方法优化都已经优化了。所以我们在平时的代码调用中,一定要尽可能的使用JDK的公共API和核心库,这样才能充分利用内置方法的特性,从而提升程序效率。
Hotspot VM中的内置方法
那么对于Hotspot VM来说,内置的方法有哪些呢?
Hotspot VM中所有的内置方法都在src/share/vm/classfile/vmSymbols.hpp类中:
上图我只截取了部分标记为intrinsic方法的类的说明。
可以看到java.lang.Math中大部分的方法都是intrinsic的方法。
怎么查看我们代码中调用的方法是不是intrinsic方法呢?
很简单,在java命令之前加上这些参数即可:
-XX:+UnlockDiagnosticVMOptions -XX:+PrintCompilation -XX:+PrintInlining
举个最常用的查看java版本的例子:
java -XX:+UnlockDiagnosticVMOptions -XX:+PrintCompilation -XX:+PrintInlining version
看下输出结果:
从结果可以很清楚的看到,java.lang.System.arraycopy方法是内置方法。
另外我们可以通过更加底层的汇编语言来查看,再添加
-XX:+PrintAssembly
我们看下输出结果:
invokestatic意味着该方法就是intrinsified方法。
intrinsic方法和内联方法
内联方法就是把调用方函数代码"复制"到调用方函数中,减少因函数调用开销的技术。
intrinsic方法大部分都是内联方法。
intrinsic方法的实现
前面我们提到了内置方法是在编译器实现的。
在Hotspot VM中其实有3中编译器。
第一种就是javac将java源代码编译成为字节码。
在这一层,只有一些math方法和bootstrapping的MethodHandle是在这一层实现的。
第二种就是在JIT的Client Compiler (C1)。
第三种就是在JIT的Server Compiler (C2)。
举一个例子,我们看一下java.lang.System.currentTimeMillis()方法:
@HotSpotIntrinsicCandidate
public static native long currentTimeMillis();
JDK源码使用了HotSpotIntrinsicCandidate注解。这个注解只是表示该方法可能会被用于Intrinsic,而并不意味着一定使用Intrinsic。
这个方法在Interpreter级别是没有intrinsified。因为这是一个native方法,所以会通过JNI调用底层的C++实现。
而在C1和C2级别,会使用intrinsified, 直接调用os::javaTimeMillis()。
好处就是减少了JNI的使用,提升效率。
好了问题来了,我们可以自己实现intrinsified方法吗?
答案是可以,不过需要修改底层的JVM实现。
这里有两个具体的例子,感兴趣的大家可以自行研究。
C1级别修改(First cut: C1 Class.isInstance intrinsic):
https://gist.github.com/rednaxelafx/2830194
C2级别修改(Example (XS) of adding an intrinsic method to HotSpot C2. Patch against HS20-b12):
https://gist.github.com/rednaxelafx/1986224
Graal
因为Hotspot VM是用C++编写的,如果要添加Intrinsic方法,对于那些不熟悉C++的朋友来说就太难了。
没关系,Oracle开发了一个项目叫做Graal。 Graal是一个用java编写的新款JIT编译器。
Graal是基于Java的JIT编译器,是JDK 9中引入的实验性Ahead-of-Time(AOT)编译器的基础。
开启Graal的参数:
-XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler
通过Graal,我们可以用java来实现Intrinsic方法,想想就让人兴奋。
总结
Intrinsic方法是一个非常有用的特性,希望大家能够喜欢。
本文作者:flydean程序那些事
本文链接:http://www.flydean.com/jvm-intrinsic-method/
本文来源:flydean的博客
欢迎关注我的公众号:程序那些事,更多精彩等着您!
JVM详解之:HotSpot VM中的Intrinsic methods的更多相关文章
- JVM详解总结
JVM详解总结 1.JVM内存模型 1.1 运行时数据区内存分布实例 1.2 类加载的生命周期 2.物理内存与虚拟内存 3.Java中需要使用内存的组件 3.1 Java堆 3.2 线程 3.3 类和 ...
- HotSpot VM 中的JIT分类
在HotSpot VM中内嵌有两个JIT编译器,分别为Client Compiler和Server Compiler,但大多数情况下我们简称为C1编译器和C2编译器.开发人员可以通过如下命令显式指定J ...
- JVM 详解,大白话带你认识 JVM
前言 如果在文中用词或者理解方面出现问题,欢迎指出.此文旨在提及而不深究,但会尽量效率地把知识点都抛出来 一.JVM的基本介绍 JVM 是 Java Virtual Machine 的缩写,它是一个虚 ...
- JVM详解(五)——运行时数据区-方法区
一.概述 1.介绍 <Java虚拟机规范>中明确说明:尽管所有的方法区在逻辑上属于堆的一部分,但一些简单的实现可能不会选择去进行垃圾收集或者进行压缩.但对于HotSpot JVM而言,方法 ...
- Scala 深入浅出实战经典 第61讲:Scala中隐式参数与隐式转换的联合使用实战详解及其在Spark中的应用源码解析
王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载: 百度云盘:http://pan.baidu.com/s/1c0noOt ...
- Scala 深入浅出实战经典 第60讲:Scala中隐式参数实战详解以及在Spark中的应用源码解析
王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...
- 详解OJ(Online Judge)中PHP代码的提交方法及要点【举例:ZOJ 1001 (A + B Problem)】
详解OJ(Online Judge)中PHP代码的提交方法及要点 Introduction of How to submit PHP code to Online Judge Systems Int ...
- 详解Linux下iptables中的DNAT与SNAT设置(转)
详解Linux下iptables中的DNAT与SNAT设置 这篇文章主要介绍了Linux下iptables中的DNAT与SNAT设置,是Linux网络配置中的基础知识,需要的朋友可以参考下 原文连 ...
- Java网络编程和NIO详解1:JAVA 中原生的 socket 通信机制
Java网络编程和NIO详解1:JAVA 中原生的 socket 通信机制 JAVA 中原生的 socket 通信机制 摘要:本文属于原创,欢迎转载,转载请保留出处:https://github.co ...
随机推荐
- python中的守护线程
什么是守护线程:在后台运行,为其他线程提供服务的线程成为守护线程. 为什么要引入守护线程: thread模块不支持守护线程的概念,当主线程退出时,所有的子线程都将终止,不管它们是否仍在工作, 如果你不 ...
- HTTPS 和 SSL/TLS 协议:密钥交换(密钥协商)算法及其原理
转自:https://blog.csdn.net/andylau00j/article/details/54583769 本系列的前一篇,咱们聊了“密钥交换的难点”以及“证书体系”的必要性.今天这篇来 ...
- 收藏 | 14张思维导图-构建Python核心体系!Python语法总结!
今天在看Python时,ZOE的Python思维导图总结的很好,分享一下 链接: https://pan.baidu.com/s/1s6Gtptp-pJS0UliNeRIvjg 提取码: mrfz
- OAuth 2.0 授权方式讲解,规范实践和应用
基于实践说规范 网上看了一些OAuth 2.0的授权方法,尽管讲解的没有什么逻辑性错误,但是存在一个问题,那就是单纯的讲解协议规范却脱离了实际的应用,缺少干货,所以才有了这篇文章,内容基于实际业务进行 ...
- CF3D Least Cost Bracket Sequence 题解
题目 This is yet another problem on regular bracket sequences. A bracket sequence is called regular, i ...
- 通过调试对WriteFile()API的钩取
通过调试对WriteFile()API的钩取 0x00 目标与思路 目标:钩取指定的notepad.exe进程writeFile()API函数,对notepad.exe进程的写入的字符保存时保存为大写 ...
- day13 函数入门
目录 一.什么是函数 二.为何要有函数 三.如何用函数 1.定义函数的三种形式: 形式一.无参函数(自身能干活) 形式二.有参函数(需要外部的材料来加工) 形式三.空函数(在写框架构思函数的时候) 2 ...
- 《Spring全局异常处理》从零掌握@ControllerAdvice注解
一.开门见山 在前后端分离框架的大趋势下,前后端基本的职责已经确定. 前端主要负责界面的处理以及基本的判空检验.数据来源则通过vue调用后端发布的接口. 后端的原型还是mvc的模式: controll ...
- 03 Django模型层: 常用(非常用)字段和参数
Django模型层: 常用(非常用)字段和参数 1 ORM字段 AutoField int自增列,必须填入参数 primary_key=True.当model中如果没有自增列,则自动会创建一个列名为i ...
- buu[护网杯 2018]easy_tornado
[护网杯 2018]easy_tornado 1.看看题目给了我们三个文件: /flag.txt url=?filename=/flag.txt&filehash=98c6aac4fbecf1 ...