JAVA 隐藏类(Hidden Classes)

2021-03-04  本文已影响0人  一万年不是尽头

简介

来自JEP371
隐藏类,其他类的字节码不能直接使用的类。隐藏类适用于在运行时生成类并通过反射间接使用它们。隐藏类可以定义为访问控制嵌套的成员,并且可以独立于其他类进行卸载。

原因

近几年,产生很多基于jvm的动态语言,例如groovy,kotlin等,基本都是基于动态代理来实现动态语言的功能的,而像lambda表达式,也是在运行过程中传输一个字节码,而该字节码可以动态生成一个类并且实例化。

这样就会在程序执行的过程中产生很多的类,二基于传统关于定于标准java类的api上看(ClassLoader::defineClassLookup::defineClass)这些动态生成的类根本无法被识别出来。这样这些动态类型很容易被发现,并且声明周期会变得很长。

如果可以从标准API去定义一个可以隐藏且生命周期有限的类,那么肯定能够提高所有基于jvm的语言的实现效率,例如:

创建一个隐藏类

defineHiddenClass(byte[] bytes, boolean initialize, ClassOption... options)有三个参数

隐藏类的使用

Lookup::defineHiddenClass会返回一个Lookup对象,我们可以调用Lookup::lookupClass获取这个隐藏类的类型,隐藏类和普通的类一样使用,但是会有以下四点注意的地方:

  1. Class::getName 返回不是二进制名称的字符串

  2. Class::getCanonicalName返回值是null,表示示隐藏的类没有全限定名。(注意,Java语言中的匿名类对象该方法的返回值也是null。)

  3. 在隐藏类中声明的所有字段都是不可修改的,无论是使用Field::set还是其他修改字段的方法都会抛出IllegalAccessException(包括反射设置accessibleTrue时)

  4. 隐藏类对象不能被 instrumentation agents修改,也不能被JVM TI agents重新定义或转换。

调试中跟踪隐藏类

添加启动参数

-XX:+UnlockDiagnosticVMOptions
-XX:+ShowHiddenFrames

有三个api可以获取隐藏类的堆栈信息

Throwable::getStackTrace
Thread::getStackTrace
StackWalkerAPI
上一篇 下一篇

猜你喜欢

热点阅读