笔者在学习jdk源码的时候,发现jdk里的一些类的私有方法挺有意思的,然后就想通过反射机制调用这些私有方法,结果不出我所料,私有方法是调用不了的,那么,为什么我们自己定义的类,通过反射机制,即使方法是私有的,却能(通过setAccessible(true)方法)绕过安全检查调用,而调用jdk自带的类的私有方法却做不到呢,带着这样的疑问,深入源码来看一下;
比如我现在看到JDK中LinkedList类有一个私有方法 isPositionIndex(int index),我想通过反射机制来调用这个这个方法试试:
结果发现直接就抛出了异常,说找不到这个方法,可是明明jdk有这个方法,这个时候我们查看下getDeclaredMethod方法做了什么,为什么会报这个错误呢?
原来在查找所有类的方法之前,这个方法调用了checkMemberAccess方法,这个方法做了什么呢?让我们继续深入查看
原来这个方法调用了SecurityManager类,java的安全机制管理类,然后对载入的类进行判断,这个就涉及到jvm中类的加载顺序,我们知道当我们加载一个类的时候,首先看是否能在boot上加载,然后再看能不能在extend上加载,最后通过application的加载,如果都加载不到,就报异常,当方法发现载入的类是和jdk自带的类是一个地方上加载的,则说明是jdk自带的类,这个时候就给这个类的私有方法加了权限,就无法调用了,也就报了截图中的那段错误了,这里涉及到两个知识点,一个是SecurityManager类,另一个就是jvm加载类顺序。
public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException, InstantiationException {
Method priList = LinkedList.class.getDeclaredMethod("isPositionIndex",Integer.class);
priList.setAccessible(true);
int i = (int) priList.invoke(LinkedList.class.newInstance(), 2);
System.out.println(i);
}
Exception in thread "main" java.lang.NoSuchMethodException: java.util.LinkedList.isPositionIndex(java.lang.Integer)
at java.lang.Class.getDeclaredMethod(Class.java:2130)
at com.crossoverjie.actual.CopyOfReadFile.main(CopyOfReadFile.java:52)
截图1:
截图2: