java7新特性之方法句柄MethodHandle使用

简介: java7新特性之方法句柄MethodHandle使用

场景


今天看jvm虚拟机初始化的阶段时候,发现有下面5种情况,会触发初始化


初始化阶段,虚拟机规范则是严格规定了有且只有5种情况必须立即对类进行“初始化”(而加载、验证、准备自然需要在此之前开始):


1)遇到new、getstatic、putstatic或invokestatic这4条字节码指令时,如果类没有进行过初始化,则需要先触发其初始化。生成这4条指令的最常见的Java代码场景是:使用new关键字实例化对象的时候、读取或设置一个类的静态字段(被final修饰、已在编译期把结果放入常量池的静态字段除外)的时候,以及调用一个类的静态方法的时候。


2)使用java.lang.reflect包的方法对类进行反射调用的时候,如果类没有进行过初始化,则需要先触发其初始化。


3)当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化。


4)当虚拟机启动时,用户需要指定一个要执行的主类(包含main()方法的那个类),虚拟机会先初始化这个主类。


5)当使用JDK 1.7的动态语言支持时,如果一个java.lang.invoke.MethodHandle实例最后的解析结果REF_getStatic、REF_putStatic、REF_invokeStatic的方法句柄,并且这个方法句柄所对应的类没有进行过初始化,则需要先触发其初始化。


其中第5条没接触过,饿补了一下MethodHandle的使用场景。


MethodHandle


JDK6之前我们会使用java反射来实现动态方法调用,多数框架用反射的比较多,例如mybatis、spring等。在JDK7中,新增了java.lang.invoke.MethodHandle(方法句柄),称之为“现代化反射”。其实反射和java.lang.invoke.MethodHandle都是间接调用方法的途径,但java.lang.invoke.MethodHandle比反射更简洁,用反射功能会写一大堆冗余代码。


官方api给出的解释:


A method handle is a typed, directly executable reference to an underlying method, constructor, field, or similar low-level operation, with optional transformations of arguments or return values.其实就是可以获取方法的句柄,类似方法的指针。


 下面看一个例子,使用方法句柄(MethodHandle)调用toString()方法:



import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
/**
 * Created by hfl on 2020/12/11
 */
public class MHTestDemo {
    public String toString(String s) {
        return "hello," + s + "MethodHandle";
    }
    public static void main(String[] args) {
        MHTestDemo mhTest = new MHTestDemo();
        MethodHandle mh = getToStringMH();  //获取方法句柄
        try {
            // 1.调用方法:
            String result = (String) mh.invokeExact(mhTest, "ssssss");  //根据方法句柄调用方法----注意返回值必须强转
            System.out.println(result);
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        // 2.or like this:
        try {
            MethodHandle methodHandle2 = mh.bindTo(mhTest);
            String toString2 = (String) methodHandle2.invokeWithArguments("sssss");
            System.out.println(toString2);
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        // 得到当前Class的不同表示方法,最后一个最好。一般我们在静态上下文用SLF4J得到logger用。
        System.out.println(MHTestDemo.class);
        System.out.println(mhTest.getClass());
        System.out.println(MethodHandles.lookup().lookupClass()); // like getClass()
    }
    /**
     * 获取方法句柄
     * @return
     */
    public static MethodHandle getToStringMH() {
        //获取方法类型 参数为:1.返回值类型,2方法中参数类型
        MethodType mt = MethodType.methodType(String.class, String.class);
        MethodHandle mh = null;
        try {
            //查找方法句柄
            mh = MethodHandles.lookup().findVirtual(MHTestDemo.class, "toString", mt);
        } catch (NoSuchMethodException | IllegalAccessException e) {
            e.printStackTrace();
        }
        return mh;
    }
}


运行结果:


hello,ssssssMethodHandle
hello,sssssMethodHandle
class com.gupao.gpjvm.ch01.MHTestDemo
class com.gupao.gpjvm.ch01.MHTestDemo
class com.gupao.gpjvm.ch01.MHTestDemo


本文完。


相关文章
java.lang.NullPointerExceptionMybatisPlus出现,测试,java.lang.NullPointe,空指针异常,public方法少写了一个字段,没加注解
java.lang.NullPointerExceptionMybatisPlus出现,测试,java.lang.NullPointe,空指针异常,public方法少写了一个字段,没加注解
|
4天前
|
算法 Java 数据处理
解决Java中堆栈溢出错误的方法
解决Java中堆栈溢出错误的方法
|
3天前
|
Java 数据处理 数据库
Java中equalsIgnoreCase方法的应用
Java中equalsIgnoreCase方法的应用
|
3天前
|
存储 Java 程序员
Java中的国际化与本地化实现方法
Java中的国际化与本地化实现方法
|
3天前
|
Java 程序员 API
Java JDK 8新特性详解及应用实例
Java JDK 8新特性详解及应用实例
|
3天前
|
JSON NoSQL Java
Redis18的Java客户端-StringRedisTemplate,序列化存在的问题,使用StringRedisTemplate解决序列化的方法
Redis18的Java客户端-StringRedisTemplate,序列化存在的问题,使用StringRedisTemplate解决序列化的方法
|
4天前
|
Java 网络架构 程序员
解决Java中的NoRouteToHostException异常的方法
解决Java中的NoRouteToHostException异常的方法
|
4天前
|
Java
解决Java中的EOFException异常的方法
解决Java中的EOFException异常的方法
|
1天前
|
Java 开发者 UED
Java中的并发编程:解锁多线程的力量
【7月更文挑战第7天】在Java的世界中,掌握并发编程是提升应用性能和响应能力的关键。本文将深入探讨如何在Java中高效地使用多线程,包括创建和管理线程、同步机制、以及避免常见的并发陷阱。我们将一起探索锁、线程池、并发集合等工具,并了解如何通过这些工具来优化程序的性能和稳定性。
|
3天前
|
监控 安全 Java
Java中的线程调度与性能优化技巧
Java中的线程调度与性能优化技巧