简介

内置方法是什么呢?它和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的更多相关文章

  1. JVM详解总结

    JVM详解总结 1.JVM内存模型 1.1 运行时数据区内存分布实例 1.2 类加载的生命周期 2.物理内存与虚拟内存 3.Java中需要使用内存的组件 3.1 Java堆 3.2 线程 3.3 类和 ...

  2. HotSpot VM 中的JIT分类

    在HotSpot VM中内嵌有两个JIT编译器,分别为Client Compiler和Server Compiler,但大多数情况下我们简称为C1编译器和C2编译器.开发人员可以通过如下命令显式指定J ...

  3. JVM 详解,大白话带你认识 JVM

    前言 如果在文中用词或者理解方面出现问题,欢迎指出.此文旨在提及而不深究,但会尽量效率地把知识点都抛出来 一.JVM的基本介绍 JVM 是 Java Virtual Machine 的缩写,它是一个虚 ...

  4. JVM详解(五)——运行时数据区-方法区

    一.概述 1.介绍 <Java虚拟机规范>中明确说明:尽管所有的方法区在逻辑上属于堆的一部分,但一些简单的实现可能不会选择去进行垃圾收集或者进行压缩.但对于HotSpot JVM而言,方法 ...

  5. Scala 深入浅出实战经典 第61讲:Scala中隐式参数与隐式转换的联合使用实战详解及其在Spark中的应用源码解析

    王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载: 百度云盘:http://pan.baidu.com/s/1c0noOt ...

  6. Scala 深入浅出实战经典 第60讲:Scala中隐式参数实战详解以及在Spark中的应用源码解析

    王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...

  7. 详解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 ...

  8. 详解Linux下iptables中的DNAT与SNAT设置(转)

    详解Linux下iptables中的DNAT与SNAT设置 这篇文章主要介绍了Linux下iptables中的DNAT与SNAT设置,是Linux网络配置中的基础知识,需要的朋友可以参考下   原文连 ...

  9. Java网络编程和NIO详解1:JAVA 中原生的 socket 通信机制

    Java网络编程和NIO详解1:JAVA 中原生的 socket 通信机制 JAVA 中原生的 socket 通信机制 摘要:本文属于原创,欢迎转载,转载请保留出处:https://github.co ...

随机推荐

  1. Nginx平滑升级详细步骤-113p.cn

    认识平滑升级 有时候我们需要对Nginx版本进行升级以满足运维人员对其功能的需求,例如添加xxx模块,需要xxx功能,而此时Nginx又在跑着业务无法停掉,这时我们就只能平滑升级了. 平滑升级原理 N ...

  2. 基于git的博客(含站点与小程序)

    1 效果 静态站点: blog.makergyt.com 备用链接: github.blog.makergyt.com 小程序: 语雀:<MakerGYT blog> 2 需求分析 2.1 ...

  3. 区间DP之凸多边形的三角剖分

    题目 给定一具有N个顶点(从1到N编号)的凸多边形,每个顶点的权均已知.问如何把这个凸多边形划分成N-2个互不相交的三角形,使得这些三角形顶点的权的乘积之和最小? 输入 第一行 顶点数N(N<5 ...

  4. input函数报错"*** is not defined"

    #键盘输入输出name = input('input your name: ') print("姓名:"+name) 运行结果: 只需要在输入时加引号,如"yu" ...

  5. 2018年BRATS 肿瘤分割挑战赛第三名分割方案One-pass Multi-task Networks with Cross-task Guided Attention for Brain Tumor Segmentation

    首先说一下我对这个方案的看法,相比第一名与第二名的方案,这个方案的分割方法确实复杂的多,原论文是发表在MICCAI,后来砖投到IEEE image processing(SCI 1区),总体感觉给人一 ...

  6. day04 python入门(变量,基本数据类型)

    python入门学习 来自egon的学习套路 在每次遇到一个新事物的时候,要学三步: xxx是什么? 为什么要有xxx? ​ 大前提:python中所有出现的语法都是为了让计算机能够具有人的某一个功能 ...

  7. 题解:2018级算法第六次上机 C6-不Nan的过河

    题目描述: 样例: 实现解释: 一道因为没排序做了一个小时没做出来的二分答案模板题(手动呲牙) 知识点: 二分答案,最大值最小化 坑点: 排序,judge(mid)函数内计数的实现 其实从最长一步的最 ...

  8. redis(二十三):Redis 集群(proxy 型)二

    redis的确是一个非常高效的缓存服务器,但是单台redis服务器的内存管理能力有限,如果一味的加大内存的话会导致redis服务器的性能下降,所以就必须要搭建redis集群来提供服务.在redis官方 ...

  9. 数据可视化之DAX篇(二十二)一文搞懂Power BI中的排名问题

    https://zhuanlan.zhihu.com/p/68384001 本文聊聊在PowerBI中如何进行各种类型的排名问题. PowerBI中计算排名主要使用RANKX函数,关于该函数的具体语法 ...

  10. Apache Hudi重磅特性解读之存量表高效迁移机制

    1. 摘要 随着Apache Hudi变得越来越流行,一个挑战就是用户如何将存量的历史表迁移到Apache Hudi,Apache Hudi维护了记录级别的元数据以便提供upserts和增量拉取的核心 ...