Method的invoke方法初步了解
Java調試過程中,我們有時候會需要對JVM運行過程中哪出了問題進行調試,先從最基礎的了解。
?
我們都知道Java框架中方法的調用基本上都是通過反射機制來實施的,具體流程如下:
?
1、方法的調用先檢查AccessibleObject的override屬性是否是true,如果是則表明該方法是復寫的方法,可以忽略訪問權限的限制,直接訪問。如果不是則進行訪問權限檢測,用sun.reflect.Reflection的quickCheckMemberAccess方法先檢驗是不是public,如果不是則再用sun.reflect.Reflection.getCallerClass()方法獲得調用這個方法的Class,然后再做是否有權限訪問的校驗,檢驗之后會將結果緩存
?
2、sun.reflect.ReflectionFactory調用方法newMethodAccessor創建方法訪問器時,私有靜態變量noInflation如果為true則直接返回MethodAccessorGenerator創建的一個MethodAccessor,否則返回DelegatingMethodAccessorImpl類,并將DelegatingMethodAccessorImpl與一個NativeMethodAccessorImpl互相引用。但DelegatingMethodAccessorImpl執行invoke方法的時候又委托給NativeMethodAccessorImpl。
?
3、NativeMethodAccessorImpl的invkoe方法,NativeMethodAccessorImpl類中有一個計數器numInvocations,每調用一次方法自增加1一次,當比?ReflectionFactory的靜態常量inflationThreshold(15)大的時候,用MethodAccessorGenerator創建一個MethodAccessor,并把之前的DelegatingMethodAccessorImpl引用替換為現在新創建的MethodAccessorImpl(MethodAccessorGenerator創建的MethodAccessor強制類型轉換為MethodAccessorImpl),其中MethodAccessorGenerator使用了asm(assembly)字節碼動態加載技術,匯編命令有更高的執行效率。
4、Method類中的invoke方法拿到的MethodAccessor對象是被volatile變量。
總結:一個方法可以生成多個Method對象,但只有一個root對象,主要用于持有一個MethodAccessor對象,這個對象也可以認為一個方法只有一個,相當于是static的。因為Method的invoke是交給MethodAccessor執行的
我們在對加了@Test注解的方法進行debug時,JUnitCore類定義了一系列方法來啟動JUnit完成對測試類的反射執行,InvokeMethod類的evaluate方法會使用測試方法(FrameworkMethod類)的invokeExplosively調用該方法的返回結果。
?
備注:
1、
| 訪問權限 | 當前類 | 同一包 | 子類 | 其他包 |
| public | √ | √ | √ | √ |
| protect | √ | √ | √ | × |
| friendly(默認) | √ | √ | × | × |
| private | √ | × | × | × |
? ? ? ??
2、源碼中很多方法用native修飾符,這種修飾符表明方法是該方法的實現由非java語言實現(A native method is a Java method whose implementation is provided by non-java code.)。當被native修飾時,描述符塊會有一個指向該實現方法的指針。
?
3、參考:https://www.cnblogs.com/onlywujun/p/3519037.html,文中的Reflection.getCallerClass(1)方法在JDK8 版本已過時(加上@Deprecated注解),使用靜態本地方法getCallerClass()加上@CallerSensitive解決通過雙重反射提升權限的漏洞
總結
以上是生活随笔為你收集整理的Method的invoke方法初步了解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 金属制品行业B2B交易管理系统:充分整合
- 下一篇: 警务移动安全管理终端,助力广东省公安厅移