クラスローダー
機能: コンパイルされた .class ファイルを jvm にロードします。
ブートストラップ ClassLoader ルート クラス ローダー
機能: JDK および JRE のコア クラスをロードします: System、String
Extension ClassLoader 拡張クラスローダー
役割: jre-lib ディレクトリへの JAR パッケージまたはリソース ファイルのロードを担当します。
System ClassLoader システム クラス ローダー
役割: JVM の起動時に Java または javac からロード コマンドをロードする責任があります。
.class ファイルはバイトコード ファイル オブジェクト (Class クラス オブジェクト) にのみ対応します。
クラスの異なるオブジェクトは同じバイトコード ファイル オブジェクトのみを持ちます。
Class オブジェクトを取得する 3 つの方法
// 加载的字节码文件不存在项目路径中时(不是自己写的)
Class<?> aClass = Class.forName("com.huawei.java.wx.WXClient");
// 加载时该类只是被类加载器加载但是没有对象时
Class<WXClient> wxClientClass = WXClient.class;
// 已经有对象,但是要反推得到对应类的字节码文件对象
WXClient c1 = new WXClient("11");
Class<? extends WXClient> aClass1 = c1.getClass();
Reflection-Class オブジェクトの 3 つの重要なオブジェクト
フィールド オブジェクト - クラスのプロパティ オブジェクト
获取所有字段的方法:
1.得到类的所有public字段
Field[] getFields()
2. 返回类中所有的字段,包括:私、保、默、公
Field[] getDeclaredFields()
获取指定字段的方法:
1.获取某个"公有的"字段:
public Field getField(String fieldName);
2.获取某个字段(可以是私有的)
public Field getDeclaredField(String fieldName)
获取变量的类型:
Field.getType():返回这个变量的类型
Field.getGenericType():如果当前属性有签名属性类型就返回,否则就返回 Field.getType()
isEnumConstant() : 判断这个属性是否是枚举类
获取成员变量的修饰符
Field.getModifiers() 以整数形式返回由此 Field 对象表示的字段的 Java 语言修饰符
* private static final 2+8+16 = 26
*
* private : 2
* (default):0
* protected: 4
* public : 1
* static : 8
* final : 16
获取和修改成员变量的值
getName() : 获取属性的名字
get(Object obj) 返回指定对象obj上此 Field 表示的字段的值
set(Object obj, Object value) 将指定对象变量上此 Field 对象表示的字段设置为指定的新值
jdk8以上のバージョンで、危険な動作をさせたい場合に追加してください。
旧JDK制作的库(JDK8及以下)运行在JDK9上会自动被标识为未命名模块,为了处理该警告,JDK9以上提出了一个新的JVM参数:--illegal-access。
该参数有四个可选值:
1.permit:默认值,允许通过反射访问,因此会提示像上面一样的警告,这个是首次非法访问警告,后续不警告
2.warn:每次非法访问都会警告
3.debug:在warn的基础上加入了类似e.printStackTrace()的功能
4.deny:禁止所有的非法访问除了使用特别的命令行参数排除的模块,比如使用--add-opens排除某些模块使其能够通过非法反射访问
因此解决的办法很简单,将其设置为deny,并添加--add-opens开启对应的允许非法反射访问的模块即可。
--illegal-access=deny --add-opens java.base/java.lang=ALL-UNNAMED
add-opens可以使模块中的包对其他模块开放,这样就可以在运行期使用深层反射访问该程序包中的所有成员类型。