日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

java反射之Method的invoke方法實(shí)現(xiàn)教程詳解

瀏覽:107日期:2022-08-18 15:50:41

前言

在框架中經(jīng)常會(huì)會(huì)用到method.invoke()方法,用來(lái)執(zhí)行某個(gè)的對(duì)象的目標(biāo)方法。以前寫(xiě)代碼用到反射時(shí),總是獲取先獲取Method,然后傳入對(duì)應(yīng)的Class實(shí)例對(duì)象執(zhí)行方法。然而前段時(shí)間研究invoke方法時(shí),發(fā)現(xiàn)invoke方法居然包含多態(tài)的特性,這是以前沒(méi)有考慮過(guò)的一個(gè)問(wèn)題。那么Method.invoke()方法的執(zhí)行過(guò)程是怎么實(shí)現(xiàn)的?它的多態(tài)又是如何實(shí)現(xiàn)的呢?

本文將從java和JVM的源碼實(shí)現(xiàn)深入探討invoke方法的實(shí)現(xiàn)過(guò)程。

首先給出invoke方法多態(tài)特性的演示代碼:

public class MethodInvoke { public static void main(String[] args) throws Exception {Method animalMethod = Animal.class.getDeclaredMethod('print');Method catMethod = Cat.class.getDeclaredMethod('print');Animal animal = new Animal();Cat cat = new Cat();animalMethod.invoke(cat);animalMethod.invoke(animal);catMethod.invoke(cat);catMethod.invoke(animal);}} class Animal {public void print() {System.out.println('Animal.print()');}} class Cat extends Animal {@Overridepublic void print() {System.out.println('Cat.print()');}}

代碼中,Cat類(lèi)覆蓋了父類(lèi)Animal的print()方法, 然后通過(guò)反射分別獲取print()的Method對(duì)象。最后分別用Cat和Animal的實(shí)例對(duì)象去執(zhí)行print()方法。其中animalMethod.invoke(animal)和catMethod.invoke(cat),示例對(duì)象的真實(shí)類(lèi)型和Method的聲明Classs是相同的,按照預(yù)期打印結(jié)果;animalMethod.invoke(cat)中,由于Cat是Animal的子類(lèi),按照多態(tài)的特性,子類(lèi)調(diào)用父類(lèi)的的方法,方法執(zhí)行時(shí)會(huì)動(dòng)態(tài)鏈接到子類(lèi)的實(shí)現(xiàn)方法上。因此,這里會(huì)調(diào)用Cat.print()方法;而catMethod.invoke(animal)中,傳入的參數(shù)類(lèi)型Animal是父類(lèi),卻期望調(diào)用子類(lèi)Cat的方法,因此這一次會(huì)拋出異常。代碼打印結(jié)果為:

Cat.print()Animal.print()Cat.print()Exception in thread 'main' java.lang.IllegalArgumentException: object is not an instance of declaring class at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at com.wy.invoke.MethodInvoke.main(MethodInvoke.java:17)

接下來(lái),我們來(lái)看看invoke()方法的實(shí)現(xiàn)過(guò)程。

public Object invoke(Object obj, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { if (!override) { if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { Class<?> caller = Reflection.getCallerClass(1); checkAccess(caller, clazz, obj, modifiers); } } MethodAccessor ma = methodAccessor; // read volatile if (ma == null) { ma = acquireMethodAccessor(); } return ma.invoke(obj, args); }

invoke()方法中主要分為兩部分:訪問(wèn)控制檢查和調(diào)用MethodAccessor.invoke()實(shí)現(xiàn)方法執(zhí)行。

首先看一下訪問(wèn)控制檢查這一塊的邏輯。第一眼看到這里的邏輯的時(shí)候,很容易搞不清楚是干嘛的。通俗來(lái)講就是通過(guò)方法的修飾符(public/protected/private/package),來(lái)判斷方法的調(diào)用者是否可以訪問(wèn)該方法。這是java的基礎(chǔ)內(nèi)容,不過(guò)用代碼寫(xiě)出來(lái),一下子不容易想到。訪問(wèn)控制檢查分為3步:

檢查override,如果override為true,跳過(guò)檢查;否則繼續(xù); 快速檢查,判斷該方法的修飾符modifiers是否為public,如果是跳過(guò)檢查;否則繼續(xù); 詳細(xì)檢查,通過(guò)方法的(protected/private/package)修飾符或方法的聲明類(lèi)(例如子類(lèi)可以訪問(wèn)父類(lèi)的protected方法)與調(diào)用者caller之間的關(guān)系,判斷caller是否有權(quán)限訪問(wèn)該方法。

override屬性是Method的父類(lèi)AccessibleObject中聲明的變量,使得程序可以控制是否跳過(guò)訪問(wèn)權(quán)限的檢查。另外,Method的實(shí)例對(duì)象中,override屬性的初始值設(shè)置為false。

public void setAccessible(boolean flag) throws SecurityException { SecurityManager sm = System.getSecurityManager(); if (sm != null) sm.checkPermission(ACCESS_PERMISSION); setAccessible0(this, flag); } private static void setAccessible0(AccessibleObject obj, boolean flag) throws SecurityException { if (obj instanceof Constructor && flag == true) { Constructor<?> c = (Constructor<?>)obj; if (c.getDeclaringClass() == Class.class) { throw new SecurityException('Can not make a java.lang.Class' + ' constructor accessible'); } } obj.override = flag; }

多說(shuō)一句,F(xiàn)ield同樣繼承了AccessibleObject,且Field的override也是初始化為false的,也就是說(shuō)并沒(méi)有按照變量的修飾符去初始化不同的值。但是我們?cè)谡{(diào)用Field.set(Object obj, Object value)時(shí),如果該Field是private修飾的,會(huì)因沒(méi)有訪問(wèn)權(quán)限而拋出異常,因此必須調(diào)用setAccessible(true)。此處非常容易理解為因?yàn)樽兞渴莗ublic的,所以override就被初始化為true。

invoke()方法中,訪問(wèn)控制檢查之后,就是通過(guò)MethodAccessor.invoke()調(diào)用方法。再來(lái)看一下代碼:

MethodAccessor ma = methodAccessor; // read volatile if (ma == null) { ma = acquireMethodAccessor(); } return ma.invoke(obj, args);

這里的邏輯很簡(jiǎn)單,首先將變量methodAccessor賦值給ma,在方法棧中保存一個(gè)可以直接引用的本地變量,如果methodAccessor不存在,調(diào)用acquireMethodAccessor()方法創(chuàng)建一個(gè)。

private volatile MethodAccessor methodAccessor; private Method root; private MethodAccessor acquireMethodAccessor() { // First check to see if one has been created yet, and take it // if so MethodAccessor tmp = null; if (root != null) tmp = root.getMethodAccessor(); if (tmp != null) { methodAccessor = tmp; } else { // Otherwise fabricate one and propagate it up to the root tmp = reflectionFactory.newMethodAccessor(this); setMethodAccessor(tmp); } return tmp; } void setMethodAccessor(MethodAccessor accessor) { methodAccessor = accessor; // Propagate up if (root != null) { root.setMethodAccessor(accessor); } } Method copy() { Method res = new Method(clazz, name, parameterTypes, returnType, exceptionTypes, modifiers, slot, signature, annotations, parameterAnnotations, annotationDefault); res.root = this; res.methodAccessor = methodAccessor; return res; }

綜合acquireMethodAccessor(),setMethodAccessor()以及copy()這三個(gè)方法,可以看到一個(gè)Method實(shí)例對(duì)象維護(hù)了一個(gè)root引用。當(dāng)調(diào)用Method.copy()進(jìn)行方法拷貝時(shí),root指向了被拷貝的對(duì)象。那么當(dāng)一個(gè)Method被多次拷貝后,調(diào)用一次setMethodAccessor()方法,就會(huì)將root引用所指向的Method的methodAccessor變量同樣賦值。例如:D -> C -> B -> A,其中X-> Y表示X = Y.copy(), 當(dāng)C對(duì)象調(diào)用setMethodAccessor()時(shí),B和A都會(huì)傳播賦值methodAccessor, 而D的methodAccessor還是null。緊接著,當(dāng)D需要獲取methodAccessor而調(diào)用acquireMethodAccessor()時(shí),D獲取root的methodAccessor, 那么D將和ABC持有相同的methodAccessor。

雖然Method中,通過(guò)維護(hù)root引用意圖使相同的方法始終保持只有一個(gè)methodAccessor實(shí)例,但是上述方法仍然無(wú)法保證相同的方法只有一個(gè)methodAccessor實(shí)例。例如通過(guò)copy()使ABCD保持關(guān)系:D -> C -> B -> A, 當(dāng)B對(duì)象調(diào)用setMethodAccessor()時(shí),B和A都會(huì)賦值methodAccessor, 而C、D的methodAccessor還是null。這時(shí)D調(diào)用acquireMethodAccessor()時(shí),D獲取root也就是C的methodAccessor,發(fā)現(xiàn)為空,然后就新創(chuàng)建了一個(gè)。從而出現(xiàn)了相同的方法中出現(xiàn)了兩個(gè)methodAccessor實(shí)例對(duì)象的現(xiàn)象。

在Class.getMethod()、Class.getDeclaredMethod()以及Class.getDeclaredMethod(String name, Class<?>... parameterTypes)方法中最終都會(huì)調(diào)用copy()方法來(lái)保障Method使用的安全性。 在比較極端加巧合的情況下,可能會(huì)引起類(lèi)膨脹的問(wèn)題,這就是接下來(lái)要講到的MethodAccessor的實(shí)現(xiàn)機(jī)制。

java反射之Method的invoke方法實(shí)現(xiàn)教程詳解

在前面代碼中,MethodAccessor的創(chuàng)建是通過(guò)反射工廠ReflectionFactory的newMethodAccessor(Method)方法來(lái)創(chuàng)建的。

public MethodAccessor newMethodAccessor(Method method) { checkInitted(); if (noInflation) { return new MethodAccessorGenerator(). generateMethod(method.getDeclaringClass(), method.getName(), method.getParameterTypes(), method.getReturnType(), method.getExceptionTypes(), method.getModifiers()); } else { NativeMethodAccessorImpl acc = new NativeMethodAccessorImpl(method); DelegatingMethodAccessorImpl res = new DelegatingMethodAccessorImpl(acc); acc.setParent(res); return res; } }

其中, checkInitted()方法檢查從配置項(xiàng)中讀取配置并設(shè)置noInflation、inflationThreshold的值:

private static void checkInitted() { if (initted) return; AccessController.doPrivileged( new PrivilegedAction<Void>() { public Void run() { if (System.out == null) { // java.lang.System not yet fully initialized return null; } String val = System.getProperty('sun.reflect.noInflation'); if (val != null && val.equals('true')) { noInflation = true; } val = System.getProperty('sun.reflect.inflationThreshold'); if (val != null) { try { inflationThreshold = Integer.parseInt(val); } catch (NumberFormatException e) { throw (RuntimeException) new RuntimeException('Unable to parse property sun.reflect.inflationThreshold'). initCause(e); } } initted = true; return null; } }); }

可以通過(guò)啟動(dòng)參數(shù)-Dsun.reflect.noInflation=false -Dsun.reflect.inflationThreshold=15來(lái)設(shè)置:

java反射之Method的invoke方法實(shí)現(xiàn)教程詳解

結(jié)合字面意思及下面代碼理解,這兩個(gè)配置sun.reflect.noInflation是控制是否立即進(jìn)行類(lèi)膨脹,sun.reflect.inflationThreshold是設(shè)置類(lèi)膨脹閾值。

創(chuàng)建MethodAccessor有兩種選擇,一種是當(dāng)sun.reflect.noInflation配置項(xiàng)為true時(shí),ReflectionFactory利用MethodAccessor的字節(jié)碼生成類(lèi) MethodAccessorGenerator直接創(chuàng)建一個(gè)代理類(lèi),通過(guò)間接調(diào)用原方法完成invoke()任務(wù),具體實(shí)現(xiàn)稍后給出。MethodAccessor的另一種實(shí)現(xiàn)方式是,創(chuàng)建DelegatingMethodAccessorImpl 委托類(lèi),并將執(zhí)行invoke()方法的具體內(nèi)容交由NativeMethodAccessorImpl實(shí)現(xiàn),而NativeMethodAccessorImpl最終調(diào)用native方法完成invoke()任務(wù)。以下是NativeMethodAccessorImpl的invoke()方法實(shí)現(xiàn)。

public Object invoke(Object obj, Object[] args) throws IllegalArgumentException, InvocationTargetException { if (++numInvocations > ReflectionFactory.inflationThreshold()) { MethodAccessorImpl acc = (MethodAccessorImpl) new MethodAccessorGenerator(). generateMethod(method.getDeclaringClass(), method.getName(), method.getParameterTypes(), method.getReturnType(), method.getExceptionTypes(), method.getModifiers()); parent.setDelegate(acc); } return invoke0(method, obj, args); } private static native Object invoke0(Method m, Object obj, Object[] args);

可以看到,當(dāng)numInvocations數(shù)量大于配置項(xiàng)sun.reflect.inflationThreshold即類(lèi)膨脹閾值時(shí), 使用MethodAccessorGenerator創(chuàng)建一個(gè)代理類(lèi)對(duì)象,并且將被委托的NativeMethodAccessorImpl的parent,也就是委托類(lèi)DelegatingMethodAccessorImpl的委托類(lèi)設(shè)置為這個(gè)生成的代理對(duì)象。這么說(shuō)可能有點(diǎn)繞,下面用一幅圖表示這個(gè)過(guò)程。

java反射之Method的invoke方法實(shí)現(xiàn)教程詳解

總體來(lái)說(shuō),當(dāng)調(diào)用invoke()時(shí),按照默認(rèn)配置,Method首先創(chuàng)建一個(gè)DelegatingMethodAccessorImpl對(duì)象,并設(shè)置一個(gè)被委托的NativeMethodAccessorImpl對(duì)象,那么method.invoke()就被轉(zhuǎn)換成DelegatingMethodAccessorImpl.invoke(),然后又被委托給NativeMethodAccessorImp.invoke()實(shí)現(xiàn)。當(dāng)NativeMethodAccessorImp.invoke()調(diào)用次數(shù)超過(guò)一定熱度時(shí)(默認(rèn)15次),被委托方又被轉(zhuǎn)換成代理類(lèi)來(lái)實(shí)現(xiàn)。

之前提到過(guò)在極端情況下,同一個(gè)方法的Method對(duì)象存在多個(gè)不同拷貝拷貝時(shí),可能存在多個(gè)MethodAccessor對(duì)象。那么當(dāng)多次調(diào)用后,必然會(huì)生成兩個(gè)重復(fù)功能的代理類(lèi)。當(dāng)然,一般情況下,生成兩個(gè)代理類(lèi)并沒(méi)有較大的影響。

其中代理類(lèi)的具體字節(jié)碼實(shí)現(xiàn)過(guò)程較為復(fù)雜,大體思想是生成一個(gè)如下所示的類(lèi):

public class GeneratedMethodAccessor1 extends MethodAccessorImpl { public GeneratedMethodAccessor1 () { super();}public Object invoke(Object obj, Object[] args) throws IllegalArgumentException, InvocationTargetException {if (!(obj instanceof Cat)) {throw new ClassCastException();}if (args != null && args.length != 0) {throw new IllegalArgumentException();}try {Cat cat = (Cat) obj;cat.print();return null;} catch (Throwable e) {throw new InvocationTargetException(e, 'invoke error');}}}

到目前為止,除了在代理的GeneratedMethodAccessor1 類(lèi)中,方法的執(zhí)行有多態(tài)的特性,而NativeMethodAccessorImp的invoke()實(shí)現(xiàn)是在jdk中的完成的。接下來(lái)我們將目光移到NativeMethodAccessorImp的native方法invoke0();

openJDK下載地址

首先,在jdksrcsharenativesunreflect路徑下找到NativeAccessors.c, 其中有Java_sun_reflect_NativeMethodAccessorImpl _invoke0()方法,根據(jù)JNI定義函數(shù)名的規(guī)則'包名_類(lèi)名_方法名',這就是我們要找的native方法實(shí)現(xiàn)入口。

JNIEXPORT jobject JNICALL Java_sun_reflect_NativeMethodAccessorImpl_invoke0(JNIEnv *env, jclass unused, jobject m, jobject obj, jobjectArray args){ return JVM_InvokeMethod(env, m, obj, args);}

方法調(diào)用JVM_InvokeMethod(), 一般以JVM_開(kāi)頭的函數(shù)定義在jvm.cpp文件中,不熟悉的話可以通過(guò)頭文件jvm.h看出來(lái)。繼續(xù)追蹤,發(fā)現(xiàn)jvm.cpp文件位于spotsrcsharevmprims文件夾下。

JVM_ENTRY(jobject, JVM_InvokeMethod(JNIEnv *env, jobject method, jobject obj, jobjectArray args0)) JVMWrapper('JVM_InvokeMethod'); Handle method_handle; if (thread->stack_available((address) &method_handle) >= JVMInvokeMethodSlack) { method_handle = Handle(THREAD, JNIHandles::resolve(method)); Handle receiver(THREAD, JNIHandles::resolve(obj)); objArrayHandle args(THREAD, objArrayOop(JNIHandles::resolve(args0))); oop result = Reflection::invoke_method(method_handle(), receiver, args, CHECK_NULL); jobject res = JNIHandles::make_local(env, result); if (JvmtiExport::should_post_vm_object_alloc()) { oop ret_type = java_lang_reflect_Method::return_type(method_handle()); assert(ret_type != NULL, 'sanity check: ret_type oop must not be NULL!'); if (java_lang_Class::is_primitive(ret_type)) { // Only for primitive type vm allocates memory for java object. // See box() method. JvmtiExport::post_vm_object_alloc(JavaThread::current(), result); } } return res; } else { THROW_0(vmSymbols::java_lang_StackOverflowError()); }JVM_END

其中oop result = Reflection::invoke_method(method_handle(), receiver, args, CHECK_NULL)是方法的執(zhí)行過(guò)程,在hotspotsrcsharevmruntime路徑下找到reflection.cpp文件。

oop Reflection::invoke_method(oop method_mirror, Handle receiver, objArrayHandle args, TRAPS) { oop mirror = java_lang_reflect_Method::clazz(method_mirror); int slot = java_lang_reflect_Method::slot(method_mirror); bool override = java_lang_reflect_Method::override(method_mirror) != 0; objArrayHandle ptypes(THREAD, objArrayOop(java_lang_reflect_Method::parameter_types(method_mirror))); oop return_type_mirror = java_lang_reflect_Method::return_type(method_mirror); BasicType rtype; if (java_lang_Class::is_primitive(return_type_mirror)) { rtype = basic_type_mirror_to_basic_type(return_type_mirror, CHECK_NULL); } else { rtype = T_OBJECT; } instanceKlassHandle klass(THREAD, java_lang_Class::as_Klass(mirror)); Method* m = klass->method_with_idnum(slot); if (m == NULL) { THROW_MSG_0(vmSymbols::java_lang_InternalError(), 'invoke'); } methodHandle method(THREAD, m); return invoke(klass, method, receiver, override, ptypes, rtype, args, true, THREAD);} oop Reflection::invoke(instanceKlassHandle klass, methodHandle reflected_method, Handle receiver, bool override, objArrayHandle ptypes, BasicType rtype, objArrayHandle args, bool is_method_invoke, TRAPS) { ResourceMark rm(THREAD); methodHandle method; // actual method to invoke KlassHandle target_klass; // target klass, receiver’s klass for non-static // Ensure klass is initialized klass->initialize(CHECK_NULL); bool is_static = reflected_method->is_static(); if (is_static) { // ignore receiver argument method = reflected_method; target_klass = klass; } else { // check for null receiver if (receiver.is_null()) { THROW_0(vmSymbols::java_lang_NullPointerException()); } // Check class of receiver against class declaring method if (!receiver->is_a(klass())) { THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), 'object is not an instance of declaring class'); } // target klass is receiver’s klass target_klass = KlassHandle(THREAD, receiver->klass()); // no need to resolve if method is private or <init> if (reflected_method->is_private() || reflected_method->name() == vmSymbols::object_initializer_name()) { method = reflected_method; } else { // resolve based on the receiver if (reflected_method->method_holder()->is_interface()) { // resolve interface call if (ReflectionWrapResolutionErrors) { // new default: 6531596 // Match resolution errors with those thrown due to reflection inlining // Linktime resolution & IllegalAccessCheck already done by Class.getMethod() method = resolve_interface_call(klass, reflected_method, target_klass, receiver, THREAD); if (HAS_PENDING_EXCEPTION) { // Method resolution threw an exception; wrap it in an InvocationTargetException oop resolution_exception = PENDING_EXCEPTION; CLEAR_PENDING_EXCEPTION; JavaCallArguments args(Handle(THREAD, resolution_exception)); THROW_ARG_0(vmSymbols::java_lang_reflect_InvocationTargetException(), vmSymbols::throwable_void_signature(), &args); } } else { method = resolve_interface_call(klass, reflected_method, target_klass, receiver, CHECK_(NULL)); } } else { // if the method can be overridden, we resolve using the vtable index. assert(!reflected_method->has_itable_index(), ''); int index = reflected_method->vtable_index(); method = reflected_method; if (index != Method::nonvirtual_vtable_index) { // target_klass might be an arrayKlassOop but all vtables start at // the same place. The cast is to avoid virtual call and assertion. InstanceKlass* inst = (InstanceKlass*)target_klass(); method = methodHandle(THREAD, inst->method_at_vtable(index)); } if (!method.is_null()) { // Check for abstract methods as well if (method->is_abstract()) { // new default: 6531596 if (ReflectionWrapResolutionErrors) { ResourceMark rm(THREAD); Handle h_origexception = Exceptions::new_exception(THREAD, vmSymbols::java_lang_AbstractMethodError(), Method::name_and_sig_as_C_string(target_klass(), method->name(), method->signature())); JavaCallArguments args(h_origexception); THROW_ARG_0(vmSymbols::java_lang_reflect_InvocationTargetException(), vmSymbols::throwable_void_signature(), &args); } else { ResourceMark rm(THREAD); THROW_MSG_0(vmSymbols::java_lang_AbstractMethodError(), Method::name_and_sig_as_C_string(target_klass(), method->name(), method->signature())); } } } } } } // I believe this is a ShouldNotGetHere case which requires // an internal vtable bug. If you ever get this please let Karen know. if (method.is_null()) { ResourceMark rm(THREAD); THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(), Method::name_and_sig_as_C_string(klass(), reflected_method->name(), reflected_method->signature())); } // In the JDK 1.4 reflection implementation, the security check is // done at the Java level if (!(JDK_Version::is_gte_jdk14x_version() && UseNewReflection)) { // Access checking (unless overridden by Method) if (!override) { if (!(klass->is_public() && reflected_method->is_public())) { bool access = Reflection::reflect_check_access(klass(), reflected_method->access_flags(), target_klass(), is_method_invoke, CHECK_NULL); if (!access) { return NULL; // exception } } } } // !(Universe::is_gte_jdk14x_version() && UseNewReflection) assert(ptypes->is_objArray(), 'just checking'); int args_len = args.is_null() ? 0 : args->length(); // Check number of arguments if (ptypes->length() != args_len) { THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), 'wrong number of arguments'); } // Create object to contain parameters for the JavaCall JavaCallArguments java_args(method->size_of_parameters()); if (!is_static) { java_args.push_oop(receiver); } for (int i = 0; i < args_len; i++) { oop type_mirror = ptypes->obj_at(i); oop arg = args->obj_at(i); if (java_lang_Class::is_primitive(type_mirror)) { jvalue value; BasicType ptype = basic_type_mirror_to_basic_type(type_mirror, CHECK_NULL); BasicType atype = unbox_for_primitive(arg, &value, CHECK_NULL); if (ptype != atype) { widen(&value, atype, ptype, CHECK_NULL); } switch (ptype) { case T_BOOLEAN: java_args.push_int(value.z); break; case T_CHAR: java_args.push_int(value.c); break; case T_BYTE: java_args.push_int(value.b); break; case T_SHORT: java_args.push_int(value.s); break; case T_INT: java_args.push_int(value.i); break; case T_LONG: java_args.push_long(value.j); break; case T_FLOAT: java_args.push_float(value.f); break; case T_DOUBLE: java_args.push_double(value.d); break; default: THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), 'argument type mismatch'); } } else { if (arg != NULL) { Klass* k = java_lang_Class::as_Klass(type_mirror); if (!arg->is_a(k)) { THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), 'argument type mismatch'); } } Handle arg_handle(THREAD, arg); // Create handle for argument java_args.push_oop(arg_handle); // Push handle } } assert(java_args.size_of_parameters() == method->size_of_parameters(), 'just checking'); // All oops (including receiver) is passed in as Handles. An potential oop is returned as an // oop (i.e., NOT as an handle) JavaValue result(rtype); JavaCalls::call(&result, method, &java_args, THREAD); if (HAS_PENDING_EXCEPTION) { // Method threw an exception; wrap it in an InvocationTargetException oop target_exception = PENDING_EXCEPTION; CLEAR_PENDING_EXCEPTION; JavaCallArguments args(Handle(THREAD, target_exception)); THROW_ARG_0(vmSymbols::java_lang_reflect_InvocationTargetException(), vmSymbols::throwable_void_signature(), &args); } else { if (rtype == T_BOOLEAN || rtype == T_BYTE || rtype == T_CHAR || rtype == T_SHORT) narrow((jvalue*) result.get_value_addr(), rtype, CHECK_NULL); return box((jvalue*) result.get_value_addr(), rtype, CHECK_NULL); }}

Reflection::invoke_method()中調(diào)用Reflection::invoke(),然后在Reflection::invoke()方法中,當(dāng)反射調(diào)用的方法是接口方法時(shí),調(diào)用Reflection::resolve_interface_call(),該方法依賴LinkResolver::resolve_interface_call()來(lái)完成方法的動(dòng)態(tài)鏈接過(guò)程,具體實(shí)現(xiàn)就不在這里展示。

method = resolve_interface_call(klass, reflected_method, target_klass, receiver, CHECK_(NULL));

methodHandle Reflection::resolve_interface_call(instanceKlassHandle klass, methodHandle method, KlassHandle recv_klass, Handle receiver, TRAPS) { assert(!method.is_null() , 'method should not be null'); CallInfo info; Symbol* signature = method->signature(); Symbol* name = method->name(); LinkResolver::resolve_interface_call(info, receiver, recv_klass, klass, name, signature, KlassHandle(), false, true, CHECK_(methodHandle())); return info.selected_method();}

如果反射調(diào)用的方法是可以被覆蓋的方法,例如Animal.print(), Reflection::invoke()最終通過(guò)查詢虛方法表vtable來(lái)確定最終的method。

// if the method can be overridden, we resolve using the vtable index. assert(!reflected_method->has_itable_index(), ''); int index = reflected_method->vtable_index(); method = reflected_method; if (index != Method::nonvirtual_vtable_index) { // target_klass might be an arrayKlassOop but all vtables start at // the same place. The cast is to avoid virtual call and assertion. InstanceKlass* inst = (InstanceKlass*)target_klass(); method = methodHandle(THREAD, inst->method_at_vtable(index)); }

總結(jié)

1.method.invoke()方法支持多態(tài)特性,其native實(shí)現(xiàn)在方法真正執(zhí)行之前通過(guò)動(dòng)態(tài)連接或者虛方法表來(lái)實(shí)現(xiàn)。

2.框架中使用method.invoke()執(zhí)行方法調(diào)用時(shí),初始獲取method對(duì)象時(shí),可以先調(diào)用一次setAccessable(true),使得后面每次調(diào)用invoke()時(shí),節(jié)省一次方法修飾符的判斷,略微提升性能。業(yè)務(wù)允許的情況下,F(xiàn)ield同樣可以如此操作。

3.委托模式可以解決一種方案的多種實(shí)現(xiàn)之間自由切換,而代理模式只能根據(jù)傳入的被代理對(duì)象來(lái)實(shí)現(xiàn)功能。

到此這篇關(guān)于java反射之Method的invoke方法實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)java反射Method的invoke方法內(nèi)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

參考文章:

JAVA深入研究——Method的Invoke方法。

標(biāo)簽: Java
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
国产精品极品| 久久性天堂网| 日本少妇一区二区| 综合激情网站| 亚洲色图综合| 国产综合精品一区| 欧美不卡高清一区二区三区| 国产精品久久久久久久免费观看 | 欧美日韩免费看片| 成人欧美一区二区三区的电影| 成人在线视频区| av综合电影网站| 欧美中文一区二区| av不卡在线看| 亚洲视频二区| 日韩毛片一区| 国产精品多人| 成人日韩av| 99精品综合| 最新日韩欧美| 亚洲色图网站| 国产日韩欧美一区二区三区| 国产精品一区二区中文字幕| 欧美成人精品一级| 精品伊人久久久| 国产精品13p| 久久九九精品| 亚洲自啪免费| 欧美伊人影院| 国产a亚洲精品| 精品捆绑调教一区二区三区| 在线一区欧美| 青青草91视频| 97人人精品| 99视频精品免费观看| 亚洲欧洲免费| 精品免费av| 欧美在线亚洲| 日本精品在线播放| 国产在线观看www| 99视频精品| 国产精品对白| 亚洲福利国产| 欧美午夜网站| 日韩中文在线播放| 日韩午夜在线| 国产精品流白浆在线观看| 国产综合色区在线观看| 日韩精品一区第一页| 免费看久久久| 在线一区欧美| 精品一区二区三区中文字幕视频| 99久久视频| 丝袜美腿诱惑一区二区三区| 亚洲欧洲免费| 日韩免费小视频| 日本亚洲最大的色成网站www | 色天使综合视频| 日本不卡一二三区黄网| 色婷婷综合网| 亚洲精品成人一区| 美女精品一区二区| 精品欧美久久| 国产精品日本一区二区三区在线 | 亚洲欧美视频| 国产精品www994| 91精品啪在线观看国产18| 一区二区亚洲视频| 91亚洲国产高清| 亚洲精品少妇| 色爱av综合网| 国产精品国码视频| 欧美综合国产| 国产欧美一区二区三区精品酒店| 亚洲制服一区| 成人精品中文字幕| 国产精品毛片久久久| 国产农村妇女精品一区二区| 久久在线免费| 老司机精品视频网| 日韩在线成人| 激情综合网址| 精品国产乱码久久久久久樱花| 在线精品福利| 日韩欧美三区| 黄色国产精品| 日本久久黄色| 久久狠狠久久| 日韩中文字幕一区二区三区| 日韩精品麻豆| 国产成人a视频高清在线观看| 日韩av电影一区| 视频一区中文字幕国产| av一区在线| 精品五月天堂| 日韩不卡在线观看日韩不卡视频 | 91青青国产在线观看精品| 日韩激情网站| 水野朝阳av一区二区三区| 亚洲a在线视频| 高清一区二区| 国产精品成人**免费视频 | 久热精品在线| 91精品亚洲| 高潮一区二区| 欧美www视频在线观看| 亚洲人成精品久久久| 欧美日韩视频| 婷婷亚洲五月色综合| 亚洲成人二区| 久久久影院免费| 日韩免费福利视频| 国产精品一区二区中文字幕| 日韩精品免费视频人成| 视频一区在线播放| 久久亚洲二区| 在线精品一区二区| 一本综合精品| 亚洲精品无播放器在线播放| 亚洲精品亚洲人成在线观看| 蜜臀a∨国产成人精品| 精品日韩毛片| 影音国产精品| 每日更新成人在线视频| 亚洲综合不卡| 亚洲一级淫片| 亚洲人亚洲人色久| 日韩av中文在线观看| 日韩精品久久久久久久软件91| 亚洲精品影院在线观看| 午夜亚洲福利| 日韩高清电影免费| 欧美在线看片| 久久精品国产免费| 成人亚洲一区| 久久久久久久久99精品大| 久久久精品五月天| 136国产福利精品导航网址| 免费av一区| 亚洲精选成人| 国产情侣一区在线| 最新亚洲国产| 国产精品久久亚洲不卡| 精品精品国产三级a∨在线| 欧美韩日一区| 婷婷丁香综合| 中文字幕日韩欧美精品高清在线| 亚洲精品系列| 国产精品色在线网站| 国产精品毛片久久| 精品1区2区3区4区| 亚洲综合二区| 欧美亚洲人成在线| 精品免费av| 99久久精品网| 亚洲精品一级| 久久影院一区二区三区| 成人日韩在线观看| 亚洲午夜国产成人| 国产精品扒开腿做爽爽爽软件| 欧美香蕉视频| 日韩精品一级中文字幕精品视频免费观看| 日韩一区免费| yellow在线观看网址| 欧美午夜不卡影院在线观看完整版免费| 在线精品一区二区| 国产精品99精品一区二区三区∴ | 99精品99| 国产免费久久| 日韩中文在线播放| 丝袜诱惑制服诱惑色一区在线观看| 日本va欧美va瓶| 国内精品伊人| 夜夜嗨一区二区| 国产日韩精品视频一区二区三区| 国产不卡av一区二区| 五月精品视频| 91p九色成人| 久久男女视频| 日本天堂一区| 久久免费大视频| 日韩av字幕| 91精品啪在线观看国产18| 视频一区日韩精品| 国产拍在线视频| 久久午夜精品| 欧美激情另类| 日韩中文av| 99久久亚洲精品蜜臀| 日韩国产精品久久久| 天堂日韩电影| 日本不卡高清| 一区二区小说| 麻豆一区二区三区| 视频在线观看91| 日韩欧美另类一区二区| 日韩精品免费一区二区夜夜嗨 | 亚洲精品日本| 久久精品123| 国产精品亚洲欧美|