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容器的初始化過程不存