📄 natmethod.cc
字号:
// natMethod.cc - Native code for Method class./* Copyright (C) 1998, 1999, 2000, 2001 , 2002 Free Software Foundation This file is part of libgcj.This software is copyrighted work licensed under the terms of theLibgcj License. Please consult the file "LIBGCJ_LICENSE" fordetails. */#include <config.h>#include <gcj/cni.h>#include <jvm.h>#include <jni.h>#include <java/lang/reflect/Method.h>#include <java/lang/reflect/Constructor.h>#include <java/lang/reflect/InvocationTargetException.h>#include <java/lang/reflect/Modifier.h>#include <java/lang/Void.h>#include <java/lang/Byte.h>#include <java/lang/Boolean.h>#include <java/lang/Character.h>#include <java/lang/Short.h>#include <java/lang/Integer.h>#include <java/lang/Long.h>#include <java/lang/Float.h>#include <java/lang/Double.h>#include <java/lang/IllegalArgumentException.h>#include <java/lang/NullPointerException.h>#include <java/lang/Class.h>#include <gcj/method.h>#include <gnu/gcj/RawData.h>#include <stdlib.h>#if USE_LIBFFI#include <ffi.h>#else#include <java/lang/UnsupportedOperationException.h>#endifstruct cpair{ jclass prim; jclass wrap;};// This is used to determine when a primitive widening conversion is// allowed.static cpair primitives[] ={#define BOOLEAN 0 { JvPrimClass (boolean), &java::lang::Boolean::class$ }, { JvPrimClass (byte), &java::lang::Byte::class$ },#define SHORT 2 { JvPrimClass (short), &java::lang::Short::class$ },#define CHAR 3 { JvPrimClass (char), &java::lang::Character::class$ }, { JvPrimClass (int), &java::lang::Integer::class$ }, { JvPrimClass (long), &java::lang::Long::class$ }, { JvPrimClass (float), &java::lang::Float::class$ }, { JvPrimClass (double), &java::lang::Double::class$ }, { NULL, NULL }};static inline jbooleancan_widen (jclass from, jclass to){ int fromx = -1, tox = -1; for (int i = 0; primitives[i].prim; ++i) { if (primitives[i].wrap == from) fromx = i; if (primitives[i].prim == to) tox = i; } // Can't handle a miss. if (fromx == -1 || tox == -1) return false; // Boolean arguments may not be widened. if (fromx == BOOLEAN && tox != BOOLEAN) return false; // Nothing promotes to char. if (tox == CHAR && fromx != CHAR) return false; return fromx <= tox;}#ifdef USE_LIBFFIstatic inline ffi_type *get_ffi_type (jclass klass){ // A special case. if (klass == NULL) return &ffi_type_pointer; ffi_type *r; if (klass == JvPrimClass (byte)) r = &ffi_type_sint8; else if (klass == JvPrimClass (short)) r = &ffi_type_sint16; else if (klass == JvPrimClass (int)) r = &ffi_type_sint32; else if (klass == JvPrimClass (long)) r = &ffi_type_sint64; else if (klass == JvPrimClass (float)) r = &ffi_type_float; else if (klass == JvPrimClass (double)) r = &ffi_type_double; else if (klass == JvPrimClass (boolean)) { // On some platforms a bool is a byte, on others an int. if (sizeof (jboolean) == sizeof (jbyte)) r = &ffi_type_sint8; else { JvAssert (sizeof (jboolean) == sizeof (jint)); r = &ffi_type_sint32; } } else if (klass == JvPrimClass (char)) r = &ffi_type_uint16; else { JvAssert (! klass->isPrimitive()); r = &ffi_type_pointer; } return r;}#endif // USE_LIBFFIjobjectjava::lang::reflect::Method::invoke (jobject obj, jobjectArray args){ if (parameter_types == NULL) getType (); jmethodID meth = _Jv_FromReflectedMethod (this); if (! java::lang::reflect::Modifier::isStatic(meth->accflags)) { jclass k = obj ? obj->getClass() : NULL; if (! obj) throw new java::lang::NullPointerException; if (! declaringClass->isAssignableFrom(k)) throw new java::lang::IllegalArgumentException; // FIXME: access checks. // Find the possibly overloaded method based on the runtime type // of the object. meth = _Jv_LookupDeclaredMethod (k, meth->name, meth->signature); } else { // We have to initialize a static class. It is safe to do this // here and not in _Jv_CallAnyMethodA because JNI initializes a // class whenever a method lookup is done. _Jv_InitClass (declaringClass); } return _Jv_CallAnyMethodA (obj, return_type, meth, false, parameter_types, args);}jintjava::lang::reflect::Method::getModifiers (){ // Ignore all unknown flags. return _Jv_FromReflectedMethod (this)->accflags & Modifier::ALL_FLAGS;}jstringjava::lang::reflect::Method::getName (){ if (name == NULL) name = _Jv_NewStringUtf8Const (_Jv_FromReflectedMethod (this)->name); return name;}/* Internal method to set return_type and parameter_types fields. */voidjava::lang::reflect::Method::getType (){ _Jv_Method *method = _Jv_FromReflectedMethod (this); _Jv_GetTypesFromSignature (method, declaringClass, ¶meter_types, &return_type); int count = 0; if (method->throws != NULL) { while (method->throws[count] != NULL) ++count; } exception_types = (JArray<jclass> *) JvNewObjectArray (count, &java::lang::Class::class$, NULL); jclass *elts = elements (exception_types); for (int i = 0; i < count; ++i) elts[i] = _Jv_FindClass (method->throws[i], declaringClass->getClassLoader ());}void_Jv_GetTypesFromSignature (jmethodID method, jclass declaringClass, JArray<jclass> **arg_types_out, jclass *return_type_out){ _Jv_Utf8Const* sig = method->signature; java::lang::ClassLoader *loader = declaringClass->getClassLoader(); char *ptr = sig->data; int numArgs = 0; /* First just count the number of parameters. */ for (; ; ptr++) { switch (*ptr) { case 0: case ')': case 'V': break; case '[': case '(': continue; case 'B': case 'C': case 'D': case 'F': case 'S': case 'I': case 'J': case 'Z': numArgs++; continue; case 'L': numArgs++; do ptr++; while (*ptr != ';' && ptr[1] != '\0'); continue; } break; } JArray<jclass> *args = (JArray<jclass> *) JvNewObjectArray (numArgs, &java::lang::Class::class$, NULL); jclass* argPtr = elements (args); for (ptr = sig->data; *ptr != '\0'; ptr++) { int num_arrays = 0; jclass type; for (; *ptr == '['; ptr++) num_arrays++; switch (*ptr) { default: return; case ')': argPtr = return_type_out; continue; case '(': continue; case 'V': case 'B': case 'C': case 'D': case 'F': case 'S': case 'I': case 'J': case 'Z': type = _Jv_FindClassFromSignature(ptr, loader); break; case 'L': type = _Jv_FindClassFromSignature(ptr, loader); do ptr++; while (*ptr != ';' && ptr[1] != '\0'); break; } // FIXME: 2'nd argument should be "current loader" while (--num_arrays >= 0) type = _Jv_GetArrayClass (type, 0); // ARGPTR can be NULL if we are processing the return value of a // call from Constructor. if (argPtr) *argPtr++ = type;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -