Java 15 神秘登场:隐藏类解析未知领域

简介: Java 15 神秘登场:隐藏类解析未知领域

什么是隐藏类

隐藏类,是一种不能被其他类直接使用的类。引入隐藏类的主要目的是给框架来使用,使得框架可以在运行时生成类,并通过反射间接使用它们。可能有点抽象,不要紧,下面我们通过一个例子来直观的认识它!

隐藏类案例

第一步:先创建一个普通的 Java

public class JEP371HiddenClasses {
    public static String hello() {
        return "Hello World";
    }
}

第二步:编译一下,或得编译后的 class 文件。然后使用 Base64 对文件内容 Encode,你可以用各种工具,也可以用下面代码来获取:

String filePath = "JEP371HiddenClasses.class";
byte[] b = Files.readAllBytes(Paths.get(filePath));
log.info(Base64.getEncoder().encodeToString(b));

执行一下,获取到内容如下:

yv66vgAAAD0AFAoAAgADBwAEDAAFAAYBABBqYXZhL2xhbmcvT2JqZWN0AQAGPGluaXQ+AQADKClWCAAIAQAZaHR0cHM6Ly93d3cuZGlkaXNwYWNlLmNvbQcACgEALmNvbS9kaWRpc3BhY2UvZGVidWcvamF2YTE1L0pFUDM3MUhpZGRlbkNsYXNzZXMBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEAMExjb20vZGlkaXNwYWNlL2RlYnVnL2phdmExNS9KRVAzNzFIaWRkZW5DbGFzc2VzOwEABWhlbGxvAQAUKClMamF2YS9sYW5nL1N0cmluZzsBAApTb3VyY2VGaWxlAQAYSkVQMzcxSGlkZGVuQ2xhc3Nlcy5qYXZhACEACQACAAAAAAACAAEABQAGAAEACwAAAC8AAQABAAAABSq3AAGxAAAAAgAMAAAABgABAAAAAwANAAAADAABAAAABQAOAA8AAAAJABAAEQABAAsAAAAbAAEAAAAAAAMSB7AAAAABAAwAAAAGAAEAAAAGAAEAEgAAAAIAEw==

这个内容就是第一步写的类。

第三步:通过反射加载上面生成的类,并调用隐藏类中的 hello 函数,代码如下:

@Test
void testHiddenClasses() throws Throwable {
    // 加载 encode 之后的隐藏类
    String CLASS_INFO = "yv66vgAAAD0AFAoAAgADBwAEDAAFAAYBABBqYXZhL2xhbmcvT2JqZWN0AQAGPGluaXQ+AQADKClWCAAIAQAZaHR0cHM6Ly93d3cuZGlkaXNwYWNlLmNvbQcACgEALmNvbS9kaWRpc3BhY2UvZGVidWcvamF2YTE1L0pFUDM3MUhpZGRlbkNsYXNzZXMBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEAMExjb20vZGlkaXNwYWNlL2RlYnVnL2phdmExNS9KRVAzNzFIaWRkZW5DbGFzc2VzOwEABWhlbGxvAQAUKClMamF2YS9sYW5nL1N0cmluZzsBAApTb3VyY2VGaWxlAQAYSkVQMzcxSGlkZGVuQ2xhc3Nlcy5qYXZhACEACQACAAAAAAACAAEABQAGAAEACwAAAC8AAQABAAAABSq3AAGxAAAAAgAMAAAABgABAAAAAwANAAAADAABAAAABQAOAA8AAAAJABAAEQABAAsAAAAbAAEAAAAAAAMSB7AAAAABAAwAAAAGAAEAAAAGAAEAEgAAAAIAEw==";
    byte[] classInBytes = getDecoder().decode(CLASS_INFO);
    Class<?> proxy = MethodHandles.lookup()
        .defineHiddenClass(classInBytes, true, MethodHandles.Lookup.ClassOption.NESTMATE)
        .lookupClass();
    // 输出类名
    log.info(proxy.getName());
    // 输出类有哪些函数
    for(Method method : proxy.getDeclaredMethods()) {
        log.info(method.getName());
    }
    // 调用 hello 函数
    MethodHandle mh = MethodHandles.lookup().findStatic(proxy, "hello", MethodType.methodType(String.class));
    String result = (String) mh.invokeExact();
    log.info(result);
}

这里的 CLASS_INFO 内容就是上一步我们处理好的隐藏类内容,先通过 Base64 将该内容解码,然后通过反射机制来将这个隐藏类的代理创建出来。

可以看到这里创建隐藏类的时候用的是 java.lang.invoke.MethodHandles.Lookup#defineHiddenClass,而创建普通类则是用 ClassLoader::defineClass 的。而这里的三个参数分别是:

  • bytes:符合 Java 虚拟机规范的字节码
  • initialize:是否要初始化类
  • options:Java 类的类型,详见 java.lang.invoke.MethodHandles.Lookup.ClassOption

再下面的操作就是对这个类的一些内容输出和方法执行。最后我们可以尝试执行下这个测试内容,最终会获得如下输出:

JEP371HiddenClasses/0x0000000800cb0c00
hello
Hello World
  • 第一行:输出了这个隐藏类的类名
  • 第二行:输出了这个隐藏类下的方法名称
  • 第三行:调用隐藏类下的 hello 方法获得的返回内容

是不是还挺简单?如果你跟我一样平时会参与一些基础框架的开发工作的话,一定觉得这个功能还挺不错的吧,又多了一种动态功能的实现手段!

相关文章
|
22小时前
|
XML Java 测试技术
Java异常处理神器:Guava Throwables类概念与实战
【4月更文挑战第29天】在Java开发中,异常处理是保证程序稳定性和可靠性的关键。Google的Guava库提供了一个强大的工具类Throwables,用于简化和增强异常处理。本篇博客将探讨Throwables类的核心功能及其在实战中的应用。
6 2
|
4天前
|
XML Java 开发工具
阿里云大学考试Java高级题目及解析-java高级
阿里云大学考试Java高级题目及解析-java高级
|
4天前
|
SQL Java 开发工具
阿里云大学考试Java中级题目及解析-java中级
阿里云大学考试Java中级题目及解析-java中级
|
4天前
|
Java 开发工具 数据库
阿里云大学考试Java初级题目及解析-java初级
阿里云大学考试Java初级题目及解析-java初级
|
4天前
|
人工智能 安全 Java
Java8 - LocalDateTime时间日期类使用详解
Java8 - LocalDateTime时间日期类使用详解
|
5天前
|
Java
Java中的多线程编程:深入解析与实战应用
Java中的多线程编程:深入解析与实战应用
|
5天前
|
存储 安全 Java
Java并发编程中的高效数据结构:ConcurrentHashMap解析
【4月更文挑战第25天】在多线程环境下,高效的数据访问和管理是至关重要的。Java提供了多种并发集合来处理这种情境,其中ConcurrentHashMap是最广泛使用的一个。本文将深入分析ConcurrentHashMap的内部工作原理、性能特点以及它如何在保证线程安全的同时提供高并发性,最后将展示其在实际开发中的应用示例。
|
5天前
|
Java
Java输入输出流详细解析
Java输入输出流详细解析
Java输入输出流详细解析
|
6天前
|
缓存 Java 程序员
|
6天前
|
安全 Java 程序员

推荐镜像

更多