java.lang.reflect java.lang.invoke.MethodHandle

获取 Class 对象:

Class.forName():

  1. String className = "com.example.demo.reflect.ClaForRefTest";
  2. Class<?> refClass = Class.forName(className);
  1. // 首先找到调用类
  2. // 然后使用调用类的 ClassLoader 去初始化
  3. // forName0 是 native 方法
  4. public static Class<?> forName(String className)
  5. throws ClassNotFoundException {
  6. Class<?> caller = Reflection.getCallerClass();
  7. return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
  8. }

ClassLoader.loadClass():

  1. String className = "com.example.demo.reflect.ClaForRefTest";
  2. // Launcher$AppClassLoader
  3. Class<?> refClass = ClassLoader.getSystemClassLoader().loadClass(className);

方法调用:

  1. String className = "com.example.demo.reflect.ClaForRefTest";
  2. // 得到 Class 对象
  3. Class<?> refClass = Class.forName(className);
  4. // 获取方法:方法名和参数。(方法名和参数列表确定唯一方法,不区分静态非静态)
  5. Method test = refClass.getMethod("test", String.class);
  6. // 调用静态方法,不需要指定对象实例
  7. test.invoke(null, "demojie");
  8. // 得到对象实例
  9. Object refObj = refClass.newInstance();
  10. // 用对象实例和参数,调用实例方法
  11. test.invoke(refObj, "demojie");

反射获取 Unsafe:

  • Unsafe 是单例的
  • 它不允许非系统类加载器(BootstrapClassLoader)加载的类去获取的

Unsafe.getUnsafe() 方法:

  1. private static final Unsafe theUnsafe;
  2. @CallerSensitive
  3. public static Unsafe getUnsafe() {
  4. Class var0 = Reflection.getCallerClass();
  5. if (!VM.isSystemDomainLoader(var0.getClassLoader())) {
  6. throw new SecurityException("Unsafe");
  7. } else {
  8. return theUnsafe;
  9. }
  10. }

可以使用反射直接获取里面的 theUnsafe:

Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
Unsafe unsafe = (Unsafe) theUnsafe.get(null);

MethodHandle:

MethodHandles.Lookup lookup = MethodHandles.lookup();
// 方法的返回值,参数列表
MethodType methodType = MethodType.methodType(void.class, String.class);
// 找虚拟方法
MethodHandle methodHandle = lookup.findVirtual(ClaForRefTest.class, "test2", methodType);
// 使用对象调用方法
methodHandle.invokeExact(new ClaForRefTest(), "demojie");

find 的其他 API:
image.png
和反射的优缺点:

  • TODO