运行时动态获取对象的全部类型信息。
在markword中保存有对象的类型指针,这个指针会指向Class对象,这个对象保存了类型信息,就是类加载的时候会将对应的类型定义读入到内存中,markword的类型指针会指向这个类的类型定义。
所以可以通过.class来获取对象的类型信息,然后通过Class来进行保存,访问对应的类。
另外加载是动态加载的,不是静态加载的。不是一次性将所有的class读入到内存中,而是在发现缺少某一个class的时候,再把对应的类型定义读入到内存中。
获取类 + 创建对象
访问方法
获取字段
父类的字段无法继承,如果想要获取父类的方法,需要通过不加declared进行访问。
由于可以通过setAccessible(true)访问私有属性、方法,所以需要进行保证。一般是使用SecurityManager进行访问性的保证。可以自定义用户的SecurityManager,通过继承的方式。下面是一个例子。
方法一:
import java.lang.reflect.ReflectPermission;
public class SecurityManagerExample {
public static void main(String[] args) {
// 创建自定义的安全管理器
SecurityManager securityManager = new CustomSecurityManager();
// 设置自定义的安全管理器
System.setSecurityManager(securityManager);
// 尝试进行反射操作
try {
// 获取Class对象
Class<?> clazz = MyClass.class;
// 通过反射调用私有方法
clazz.getDeclaredMethod("privateMethod").invoke(new MyClass());
} catch (Exception e) {
System.out.println("Security exception: " + e.getMessage());
}
}
static class CustomSecurityManager extends SecurityManager {
@Override
public void checkPermission(java.security.Permission perm) {
// 检查反射相关的权限
if (perm instanceof ReflectPermission) {
String name = perm.getName();
if (name != null && name.startsWith("suppressAccessChecks")) {
throw new SecurityException("Reflective access is not allowed.");
}
}
}
}
static class MyClass {
private void privateMethod() {
System.out.println("This is a private method.");
}
}
}
方法二:
grant {
permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
};
import java.lang.reflect.Method;
public class SecurityPolicyExample {
public static void main(String[] args) {
// 设置安全策略文件路径
System.setProperty("java.security.policy", "path/to/mysecurity.policy");
// 启用安全管理器
System.setSecurityManager(new SecurityManager());
// 尝试进行反射操作
try {
// 获取Class对象
Class<?> clazz = MyClass.class;
// 通过反射调用私有方法
Method privateMethod = clazz.getDeclaredMethod("privateMethod");
privateMethod.setAccessible(true);
privateMethod.invoke(new MyClass());
} catch (Exception e) {
System.out.println("Security exception: " + e.getMessage());
}
}
static class MyClass {
private void privateMethod() {
System.out.println("This is a private method.");
}
}
}
在运行期间创建某一个接口的实例。
原理就是在运行期间动态创建class字节码并加载的过程。
使用proxy创建代理对象,将接口方法代理给InvokeHandler完成的。
动态代理原理是反射。InvokeHandler的调用使用了反射的.class.getMethod方法。