1. 程式人生 > >Java原始碼解析(5) —— Class(4)

Java原始碼解析(5) —— Class(4)

Class最後一部分原始碼,這一部分大都是private方法、屬性、類,都是Class本身各種方法的實現細節,涉及到了很多Class的實現原理,較為深奧,網上能找到的資料也比較少,目前只懂皮毛,僅供參考,所以,我這一部分說的可能是不正確的,需要抱著懷疑的態度看待!咳,就這樣,閃人。

//快取反射的資料資訊
private volatile transient SoftReference<ReflectionData<T>> reflectionData;
//由JVM自動增加,表示虛擬機器內,該類被重新定義的次數,JVM TI可以動態更新類定義
//關於類的動態定義這一點,可以參考:
// http://blog.csdn.net/raintungli/article/details/51655608 private volatile transient int classRedefinedCount = 0; private ReflectionData<T> reflectionData() { //獲取快取中的反射資料,如果沒啟用快取,或者沒資料,則呼叫下面方法,新建反射快取資料 } private ReflectionData<T> newReflectionData(SoftReference<ReflectionData<T>> oldReflectionData, int
classRedefinedCount) { ...... } /** * 檢視該類是否是泛型,雖然jdk上面說的是簽名的handler(雖然我也不太明白這簽名是什麼), * 但是我查到,很多地方,包括Class原始碼上面判斷泛型相關,都有類似這句程式碼: * if (getGenericSignature() != null) * 詳見:getGenericInterfaces()方法以及類似方法 */ // private native String getGenericSignature(); /** * 該類的型別倉庫,其主要作用是操作及快取該類的型別資訊以及父類資訊,比如其內就有泛型 * 工廠物件,和父類物件型別資訊及所實現的父類介面資訊 */
private transient ClassRepository genericInfo; /** * GenericsFactory:泛型工廠,用來生產及操作各種型別物件(Java型別詳見:) * http://blog.csdn.net/a327369238/article/details/52621043 */ private GenericsFactory getFactory() { return CoreReflectionFactory.make(this, ClassScope.make(this)); } private ClassRepository getGenericInfo() { if (genericInfo == null) { genericInfo = ClassRepository.make(getGenericSignature(), getFactory()); } return genericInfo; } //獲取該類的註解,本地實現,詳見getAnnotation() native byte[] getRawAnnotations(); //獲取常量池 native ConstantPool getConstantPool(); //獲取所有欄位資訊,可根據引數獲取相應訪問許可權型別欄位————————方法1 private Field[] privateGetDeclaredFields(boolean publicOnly) { //只獲取該類宣告的欄位(所有許可權型別的),其父類、父介面中宣告的並沒有 } //類似上面方法,但是返回的是public型別欄位,且包括父類、父介面中宣告定義的 //要學會看方法名字,根據英文意思大概能知道方法意義——————————方法2 private Field[] privateGetPublicFields(Set<Class<?>> traversedInterfaces){ //有反射的快取資料,則直接獲取後返回 //若沒有,則通過上面方法獲取(引數置為true) //還要加上其父類以及父介面中宣告的公共欄位 } private static void addAll(Collection<Field> c, Field[] o) { for (int i = 0; i < o.length; i++) { c.add(o[i]); } } //類似方法1 private Constructor<T>[] privateGetDeclaredConstructors(boolean publicOnly) { ...... } //類似方法1 private Method[] privateGetDeclaredMethods(boolean publicOnly) { ...... } //方法陣列類 static class MethodArray { private Method[] methods; private int length; MethodArray() { methods = new Method[20]; length = 0; } void add(Method m) { if (length == methods.length) { methods = Arrays.copyOf(methods, 2 * methods.length); } methods[length++] = m; } void addAll(Method[] ma) { for (int i = 0; i < ma.length; i++) { add(ma[i]); } } void addAll(MethodArray ma) { for (int i = 0; i < ma.length(); i++) { add(ma.get(i)); } } void addIfNotPresent(Method newMethod) { for (int i = 0; i < length; i++) { Method m = methods[i]; if (m == newMethod || (m != null && m.equals(newMethod))) { return; } } add(newMethod); } void addAllIfNotPresent(MethodArray newMethods) { ...... } int length() { return length; } Method get(int i) { return methods[i]; } void removeByNameAndSignature(Method toRemove) { ...... } void compactAndTrim() { ...... } Method[] getArray() { return methods; } } //類似方法2 private Method[] privateGetPublicMethods() { ...... } //根據欄位名稱獲取fields中欄位資訊————————方法3 private static Field searchFields(Field[] fields, String name) { } //只獲取public欄位————————方法4 private Field getField0(String name) throws NoSuchFieldException { Field res; // 首先,在本類公共欄位中搜索獲取同名欄位 if ((res = searchFields(privateGetDeclaredFields(true), name)) != null) { return res; } // 若無,則搜尋父介面同名欄位,遞迴呼叫 Class<?>[] interfaces = getInterfaces(); for (int i = 0; i < interfaces.length; i++) { Class<?> c = interfaces[i]; if ((res = c.getField0(name)) != null) { return res; } } // 若仍無,判斷該類為非介面型別,獲取父類同名欄位,遞迴呼叫 if (!isInterface()) { Class<?> c = getSuperclass(); if (c != null) { if ((res = c.getField0(name)) != null) { return res; } } } //都無,則返回空 return null; } //類似方法3 private static Method searchMethods(Method[] methods, String name, Class<?>[] parameterTypes) { ...... } //類似方法4 private Method getMethod0(String name, Class<?>[] parameterTypes) { ...... } //類似方法4 private Constructor<T> getConstructor0(Class<?>[] parameterTypes, int which) throws NoSuchMethodException { } //輔助,判斷陣列是否相等 private static boolean arrayContentsEq(Object[] a1, Object[] a2) { } //複製欄位陣列資訊 private static Field[] copyFields(Field[] arg) { Field[] out = new Field[arg.length]; ReflectionFactory fact = getReflectionFactory(); for (int i = 0; i < arg.length; i++) { out[i] = fact.copyField(arg[i]); } return out; } //複製方法陣列資訊 private static Method[] copyMethods(Method[] arg) { Method[] out = new Method[arg.length]; ReflectionFactory fact = getReflectionFactory(); for (int i = 0; i < arg.length; i++) { out[i] = fact.copyMethod(arg[i]); } return out; } //複製構造器陣列資訊 private static <U> Constructor<U>[] copyConstructors(Constructor<U>[] arg) { Constructor<U>[] out = arg.clone(); ReflectionFactory fact = getReflectionFactory(); for (int i = 0; i < out.length; i++) { out[i] = fact.copyConstructor(out[i]); } return out; } //以下四個,為獲取本類所有宣告的欄位/方法/構造器/類 private native Field[] getDeclaredFields0(boolean publicOnly); private native Method[] getDeclaredMethods0(boolean publicOnly); private native Constructor<T>[] getDeclaredConstructors0(boolean publicOnly); private native Class<?>[] getDeclaredClasses0(); //輸出型別陣列各個名稱 private static String argumentTypesToString(Class<?>[] argTypes) { ....... } private static final long serialVersionUID = 3206093459760846163L; //ObjectStreamField:序列化的物件中成員屬性的元資料資訊 private static final ObjectStreamField[] serialPersistentFields = new ObjectStreamField[0]; //獲取該類的斷言狀態,類的斷言狀態可通過類的ClassLoader設定 public boolean desiredAssertionStatus() { ...... } //上面方法的本地實現 private static native boolean desiredAssertionStatus0(Class<?> clazz); //判斷是否是列舉型別 public boolean isEnum() { return (this.getModifiers() & ENUM) != 0 && this.getSuperclass() == java.lang.Enum.class; } private static ReflectionFactory getReflectionFactory() { } //反射工廠,可以通過可個工廠對類的元資料進行操作,比如新建一個構造器、方法等 private static ReflectionFactory reflectionFactory; //系統屬性是否初始化 private static boolean initted = false; //判斷系統屬性是否已經初始化,若已經初始化,直接返回,否則初始化 private static void checkInitted() { if (initted) return; AccessController.doPrivileged(new PrivilegedAction<Void>() { public Void run() { ...... } } //如果,此類為列舉類,返回其中的列舉值,否則返回空 public T[] getEnumConstants() { T[] values = getEnumConstantsShared(); return (values != null) ? values.clone() : null; } //如果此類為列舉類,返回其中的列舉值,否則返回空 T[] getEnumConstantsShared() { ...... } //列舉值 private volatile transient T[] enumConstants = null; //將列舉轉化為map<String, T> String是每個列舉的name屬性 Map<String, T> enumConstantDirectory() { if (enumConstantDirectory == null) {//若快取中為空 T[] universe = getEnumConstantsShared();//獲取所有列舉值 if (universe == null)//為空則丟擲異常 throw new IllegalArgumentException( getName() + " is not an enum type"); Map<String, T> m = new HashMap<>(2 * universe.length); for (T constant : universe)//遍歷儲存 m.put(((Enum<?>)constant).name(), constant); enumConstantDirectory = m; } return enumConstantDirectory; } private volatile transient Map<String, T> enumConstantDirectory = null; //強制轉換,如例項為null或不是例項物件,且強制轉換不成功,丟擲異常 public T cast(Object obj) { if (obj != null && !isInstance(obj)) throw new ClassCastException(cannotCastMsg(obj)); return (T) obj;//只是簡單的進行強制轉換 } //無法強轉的報錯資訊 private String cannotCastMsg(Object obj) { return "Cannot cast " + obj.getClass().getName() + " to " + getName(); } //將呼叫這個方法的class物件轉換成由clazz引數所表示的class物件的某個子類 //可參考:http://blog.csdn.net/csywwx2008/article/details/17641405 public <U> Class<? extends U> asSubclass(Class<U> clazz) { if (clazz.isAssignableFrom(this)) return (Class<? extends U>) this; else throw new ClassCastException(this.toString()); } //獲得引數對應的註解物件資訊 public <A extends Annotation> A getAnnotation(Class<A> annotationClass) { if (annotationClass == null) throw new NullPointerException(); initAnnotationsIfNecessary(); return (A) annotations.get(annotationClass); } //判斷該註解型別是否是在該類上(有該註解) public boolean isAnnotationPresent( Class<? extends Annotation> annotationClass) { if (annotationClass == null) throw new NullPointerException(); return getAnnotation(annotationClass) != null; } //獲取該類上所有註解(包括繼承),無,則返回長度為零的註解陣列 public Annotation[] getAnnotations() { initAnnotationsIfNecessary(); return AnnotationParser.toArray(annotations); } //獲取該類上所有的宣告的註解(不包括繼承的),無,則返回長度為零的註解陣列 public Annotation[] getDeclaredAnnotations() { initAnnotationsIfNecessary(); return AnnotationParser.toArray(declaredAnnotations); } private transient Map<Class<? extends Annotation>, Annotation> annotations; private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations; //類似classRedefinedCount,最後一次註解被定義的個數 private transient int lastAnnotationsRedefinedCount = 0; //在類被反射重新定義的時候,清除快取的註解資訊 private void clearAnnotationCachesOnClassRedefinition() { if (lastAnnotationsRedefinedCount != classRedefinedCount) {//二者不相等,說明類有被重新定義 annotations = declaredAnnotations = null;//清空資訊 lastAnnotationsRedefinedCount = classRedefinedCount; } } //初始化類的註解(快取資訊:annotations和declaredAnnotations) private synchronized void initAnnotationsIfNecessary() { ...... } //註解型別資訊快取 @SuppressWarnings("UnusedDeclaration") private volatile transient AnnotationType annotationType; boolean casAnnotationType(AnnotationType oldType, AnnotationType newType) { return Atomic.casAnnotationType(this, oldType, newType); } AnnotationType getAnnotationType() { return annotationType; } transient ClassValue.ClassValueMap classValueMap; }

1.關於反射工廠ReflectionFactory,是一個很破壞安全的類:

public class Test {
    private Test(){
        System.out.println("test");
    }
    public void say(){
        System.out.println("hello world");
    }
}//按理說,Test這個類只有私有構造器,外部類不能例項化,也就不能在外呼叫say方法
public class Main{
    private static final ReflectionFactory reflectionFactory = (ReflectionFactory) AccessController
            .doPrivileged(new ReflectionFactory.GetReflectionFactoryAction());
    public static void main(String[] args) throws Exception{
        Constructor<Test> constr = reflectionFactory.newConstructorForSerialization(Test.class, Object.class.getConstructor(new Class[0]));
        Test test = constr.newInstance(new Object[0]);
        test.say();
    }
}
/**
 * 然而事實,卻是可以通過ReflectionFactory這個反射工廠新建一個Test的構造器,而後
 * 通過newInstance獲取其例項,進而訪問其成員方法,這顯然是一種對訪問許可權的破壞
 */

相關推薦

Java原始碼解析(5) —— Class(4)

Class最後一部分原始碼,這一部分大都是private方法、屬性、類,都是Class本身各種方法的實現細節,涉及到了很多Class的實現原理,較為深奧,網上能找到的資料也比較少,目前只懂皮毛,僅供參考,所以,我這一部分說的可能是不正確的,需要抱著懷疑的態度看待

Java原始碼解析(2) —— Class(1)

Class —— 反射基石   Java基本類之一,反射機制的基礎。其意義為:類的抽象,即對“類”做描述:比如類有修飾、欄位、方法等屬性,有獲得該類的所有方法、所有公有方法等方法。同時,Class也是Java型別中最重要的一種,表示原始型別(引用型別)及基本型

Java編譯(二) Java前端編譯:Java原始碼編譯成Class檔案的過程

Java編譯(二)Java前端編譯: Java原始碼編譯成Class檔案的過程               在上篇文章《Java三種編譯方式:前端編

11 java原始碼解析-Thread(草稿)

1類的宣告 public class Thread implements Runnable 實現了Runnable介面 在程式開發中只要是多執行緒肯定永遠以實現Runnable介面為主。 1.1Runnable 說明 public interface Run

Java原始碼解析系列(二)ArrayList原始碼解析

備註:以下都是基於JDK8 原始碼分析 ArrayList簡介        ArrayList 是一個數組佇列,相當於 動態陣列。與Java中的陣列相比,它的容量能動態增長。它繼承於AbstractList,實現了List, RandomAccess, Clonea

Java原始碼解析ArrayList

本文基於jdk1.8來分析ArrayList的原始碼 首先是主要的成員變數。 /** * Default initial capacity. */ private static final int DEFAULT_CAPACITY = 10; /

java原始碼解析--Map

Map集合 An object that maps keys to values. A map cannot contain duplicate keys; each key can map to

java原始碼解析S

Set A collection that contains no duplicate elements. More formally, sets contain no pair of elemen

Java原始碼解析CopyOnWriteArrayList

本文基於jdk1.8進行分析。 ArrayList和HashMap是我們經常使用的集合,它們不是執行緒安全的。我們一般都知道HashMap的執行緒安全版本為ConcurrentHashMap,那麼ArrayList有沒有類似的執行緒安全的版本呢?還真有,它就是CopyOnWriteArrayLi

Java原始碼解析阻塞佇列ArrayBlockingQueue功能簡介

本文基於jdk1.8進行分析。 阻塞佇列是java開發時常用的一個數據結構。首先看一下阻塞佇列的作用是什麼。阻塞佇列的作用,從原始碼中類的註釋中來了解,是最清晰準確的。如下圖。 ArrayBlockingQueue是一個用陣列實現的有界阻塞佇列。提供FIFO的功能。佇列頭上的元素是在佇列中呆

Java原始碼解析之可重入鎖ReentrantLock(二)

上文接Java原始碼解析之可重入鎖ReentrantLock(一)。 接下來是tryLock方法。程式碼如下。從註釋中我們可以理解到,只有當呼叫tryLock時鎖沒有被別的執行緒佔用,tryLock才會獲取鎖。如果鎖沒有被另一個執行緒佔用,那麼就獲取鎖,並立刻返回true,並把鎖計數設定為1.

Java原始碼解析之可重入鎖ReentrantLock(一)

本文基於jdk1.8進行分析。 ReentrantLock是一個可重入鎖,在ConcurrentHashMap中使用了ReentrantLock。 首先看一下原始碼中對ReentrantLock的介紹。如下圖。ReentrantLock是一個可重入的排他鎖,它和synchronized的方法

Java原始碼解析LinkedList

本文基於jdk1.8進行分析。 LinkedList和ArrayList都是常用的java集合。ArrayList是陣列,Linkedlist是連結串列,是雙向連結串列。它的節點的資料結構如下。 private static class Node<E> {

Java原始碼解析HashMap的tableSizeFor函式

aka,HashMap的容量大小必須為2的指數,即16,32,64,128這樣的值。那麼,在建構函式中,如果呼叫者指定了HashMap的初始大小不是2的指數,那麼,HashMap的tableSizeFor函式,會計算一個大於或等於給定引數的2的指數的值。先來看一下tableSizeFor函式的原始碼

Java原始碼解析HashMap成員變數

本文基於jdk1.8進行分析。 關於HashMap的簡介,可以參考這篇文章https://blog.csdn.net/li_canhui/article/details/85076521。 首先看一下HashMap的一些靜態常量。第一個是DEFAULT_INITIAL_CAPACITY,預設

Java原始碼解析HashMap簡介

本文基於jdk1.8進行分析。 HashMap是java開發中可以說必然會用到的一個集合。本文就HashMap的原始碼實現進行分析。 首先看一下原始碼中類的javadoc註釋對HashMap的解釋。如下圖。HashMap是對Map介面的基於hash表的實現。這個實現提供了map的所有可選操作

Java原始碼解析執行緒池ThreadPoolExecutor簡介

本文基於jdk1.8進行分析 Java的執行緒池是在多執行緒常見下常用的框架,因為執行緒池的原始碼實現比較冗長,我們會分多次介紹執行緒池的原始碼。本文主要介紹執行緒池的基本知識。這部分知識是基於原始碼中執行緒池類ThreadPoolExecutor的javadoc註釋的。註釋原文如下。 /*

Java原始碼解析-迭代器

自己寫一個迭代器 /** * 迭代器介面 */ interface Selector { boolean end(); Object current(); void next(); } public class Seque

Caffe原始碼解析5:Conv_Layer

Vision_layer裡面主要是包括了一些關於一些視覺上的操作,比如卷積、反捲積、池化等等。這裡的類跟data layer一樣好很多種繼承關係。主要包括了這幾個類,其中CuDNN分別是CUDA版本,這裡先不討論,在這裡先討論ConvolutionLayer BaseConvolutionLayer Co

Spring原始碼解析-5、IOC容器的依賴注入

IOC容器的初始化過程有沒有注入依賴 IOC容器的初始化過程: 1、BeanDefinition的Resource資源定位 2、BeanDefinition的載入與解析 3、BeanDefinition的註冊 這三個操作至始至終不存在Bean依賴注入。 因此: IOC容器的初始化過程不存