mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
7082263: Reflection::resolve_field/field_get/field_set are broken
Reviewed-by: kvn, dholmes, stefank, coleenp
This commit is contained in:
parent
e3342531b4
commit
cebdce4479
15 changed files with 6 additions and 1025 deletions
|
@ -244,24 +244,6 @@ SUNWprivate_1.1 {
|
||||||
JVM_Yield;
|
JVM_Yield;
|
||||||
JVM_handle_linux_signal;
|
JVM_handle_linux_signal;
|
||||||
|
|
||||||
# Old reflection routines
|
|
||||||
# These do not need to be present in the product build in JDK 1.4
|
|
||||||
# but their code has not been removed yet because there will not
|
|
||||||
# be a substantial code savings until JVM_InvokeMethod and
|
|
||||||
# JVM_NewInstanceFromConstructor can also be removed; see
|
|
||||||
# reflectionCompat.hpp.
|
|
||||||
JVM_GetClassConstructor;
|
|
||||||
JVM_GetClassConstructors;
|
|
||||||
JVM_GetClassField;
|
|
||||||
JVM_GetClassFields;
|
|
||||||
JVM_GetClassMethod;
|
|
||||||
JVM_GetClassMethods;
|
|
||||||
JVM_GetField;
|
|
||||||
JVM_GetPrimitiveField;
|
|
||||||
JVM_NewInstance;
|
|
||||||
JVM_SetField;
|
|
||||||
JVM_SetPrimitiveField;
|
|
||||||
|
|
||||||
# debug JVM
|
# debug JVM
|
||||||
JVM_AccessVMBooleanFlag;
|
JVM_AccessVMBooleanFlag;
|
||||||
JVM_AccessVMIntFlag;
|
JVM_AccessVMIntFlag;
|
||||||
|
|
|
@ -244,24 +244,6 @@ SUNWprivate_1.1 {
|
||||||
JVM_Yield;
|
JVM_Yield;
|
||||||
JVM_handle_linux_signal;
|
JVM_handle_linux_signal;
|
||||||
|
|
||||||
# Old reflection routines
|
|
||||||
# These do not need to be present in the product build in JDK 1.4
|
|
||||||
# but their code has not been removed yet because there will not
|
|
||||||
# be a substantial code savings until JVM_InvokeMethod and
|
|
||||||
# JVM_NewInstanceFromConstructor can also be removed; see
|
|
||||||
# reflectionCompat.hpp.
|
|
||||||
JVM_GetClassConstructor;
|
|
||||||
JVM_GetClassConstructors;
|
|
||||||
JVM_GetClassField;
|
|
||||||
JVM_GetClassFields;
|
|
||||||
JVM_GetClassMethod;
|
|
||||||
JVM_GetClassMethods;
|
|
||||||
JVM_GetField;
|
|
||||||
JVM_GetPrimitiveField;
|
|
||||||
JVM_NewInstance;
|
|
||||||
JVM_SetField;
|
|
||||||
JVM_SetPrimitiveField;
|
|
||||||
|
|
||||||
# miscellaneous functions
|
# miscellaneous functions
|
||||||
jio_fprintf;
|
jio_fprintf;
|
||||||
jio_printf;
|
jio_printf;
|
||||||
|
|
|
@ -41,8 +41,7 @@ CFLAGS += $(DEBUG_CFLAGS/BYFILE)
|
||||||
|
|
||||||
# Linker mapfiles
|
# Linker mapfiles
|
||||||
MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers \
|
MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers \
|
||||||
$(GAMMADIR)/make/solaris/makefiles/mapfile-vers-debug \
|
$(GAMMADIR)/make/solaris/makefiles/mapfile-vers-debug
|
||||||
$(GAMMADIR)/make/solaris/makefiles/mapfile-vers-nonproduct
|
|
||||||
|
|
||||||
# This mapfile is only needed when compiling with dtrace support,
|
# This mapfile is only needed when compiling with dtrace support,
|
||||||
# and mustn't be otherwise.
|
# and mustn't be otherwise.
|
||||||
|
|
|
@ -107,8 +107,7 @@ CFLAGS += $(DEBUG_CFLAGS/BYFILE)
|
||||||
|
|
||||||
# Linker mapfiles
|
# Linker mapfiles
|
||||||
MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers \
|
MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers \
|
||||||
$(GAMMADIR)/make/solaris/makefiles/mapfile-vers-debug \
|
$(GAMMADIR)/make/solaris/makefiles/mapfile-vers-debug
|
||||||
$(GAMMADIR)/make/solaris/makefiles/mapfile-vers-nonproduct
|
|
||||||
|
|
||||||
# This mapfile is only needed when compiling with dtrace support,
|
# This mapfile is only needed when compiling with dtrace support,
|
||||||
# and mustn't be otherwise.
|
# and mustn't be otherwise.
|
||||||
|
|
|
@ -44,8 +44,7 @@ CFLAGS += $(DEBUG_CFLAGS/BYFILE)
|
||||||
|
|
||||||
# Linker mapfiles
|
# Linker mapfiles
|
||||||
MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers \
|
MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers \
|
||||||
$(GAMMADIR)/make/solaris/makefiles/mapfile-vers-debug \
|
$(GAMMADIR)/make/solaris/makefiles/mapfile-vers-debug
|
||||||
$(GAMMADIR)/make/solaris/makefiles/mapfile-vers-nonproduct
|
|
||||||
|
|
||||||
# This mapfile is only needed when compiling with dtrace support,
|
# This mapfile is only needed when compiling with dtrace support,
|
||||||
# and mustn't be otherwise.
|
# and mustn't be otherwise.
|
||||||
|
|
|
@ -1,48 +0,0 @@
|
||||||
#
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
#
|
|
||||||
# This code is free software; you can redistribute it and/or modify it
|
|
||||||
# under the terms of the GNU General Public License version 2 only, as
|
|
||||||
# published by the Free Software Foundation.
|
|
||||||
#
|
|
||||||
# This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
# version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
# accompanied this code).
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License version
|
|
||||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
#
|
|
||||||
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
# or visit www.oracle.com if you need additional information or have any
|
|
||||||
# questions.
|
|
||||||
#
|
|
||||||
#
|
|
||||||
|
|
||||||
# Define public interface.
|
|
||||||
|
|
||||||
SUNWprivate_1.1 {
|
|
||||||
global:
|
|
||||||
# Old reflection routines
|
|
||||||
# These do not need to be present in the product build in JDK 1.4
|
|
||||||
# but their code has not been removed yet because there will not
|
|
||||||
# be a substantial code savings until JVM_InvokeMethod and
|
|
||||||
# JVM_NewInstanceFromConstructor can also be removed; see
|
|
||||||
# reflectionCompat.hpp.
|
|
||||||
JVM_GetClassConstructor;
|
|
||||||
JVM_GetClassConstructors;
|
|
||||||
JVM_GetClassField;
|
|
||||||
JVM_GetClassFields;
|
|
||||||
JVM_GetClassMethod;
|
|
||||||
JVM_GetClassMethods;
|
|
||||||
JVM_GetField;
|
|
||||||
JVM_GetPrimitiveField;
|
|
||||||
JVM_NewInstance;
|
|
||||||
JVM_SetField;
|
|
||||||
JVM_SetPrimitiveField;
|
|
||||||
};
|
|
|
@ -48,9 +48,7 @@ endif # Platform_compiler == sparcWorks
|
||||||
CFLAGS$(HOTSPARC_GENERIC) += $(OPT_CFLAGS/BYFILE)
|
CFLAGS$(HOTSPARC_GENERIC) += $(OPT_CFLAGS/BYFILE)
|
||||||
|
|
||||||
# Linker mapfiles
|
# Linker mapfiles
|
||||||
# NOTE: inclusion of nonproduct mapfile not necessary; read it for details
|
MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers
|
||||||
MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers \
|
|
||||||
$(GAMMADIR)/make/solaris/makefiles/mapfile-vers-nonproduct
|
|
||||||
|
|
||||||
# This mapfile is only needed when compiling with dtrace support,
|
# This mapfile is only needed when compiling with dtrace support,
|
||||||
# and mustn't be otherwise.
|
# and mustn't be otherwise.
|
||||||
|
|
|
@ -58,13 +58,9 @@ CFLAGS$(HOTSPARC_GENERIC) += $(OPT_CFLAGS/BYFILE)
|
||||||
# to inhibit the effect of the previous line on CFLAGS.
|
# to inhibit the effect of the previous line on CFLAGS.
|
||||||
|
|
||||||
# Linker mapfiles
|
# Linker mapfiles
|
||||||
# NOTE: inclusion of nonproduct mapfile not necessary; read it for details
|
|
||||||
ifdef USE_GCC
|
|
||||||
MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers
|
MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers
|
||||||
else
|
|
||||||
MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers \
|
|
||||||
$(GAMMADIR)/make/solaris/makefiles/mapfile-vers-nonproduct
|
|
||||||
|
|
||||||
|
ifndef USE_GCC
|
||||||
# This mapfile is only needed when compiling with dtrace support,
|
# This mapfile is only needed when compiling with dtrace support,
|
||||||
# and mustn't be otherwise.
|
# and mustn't be otherwise.
|
||||||
MAPFILE_DTRACE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-$(TYPE)
|
MAPFILE_DTRACE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-$(TYPE)
|
||||||
|
|
|
@ -206,7 +206,6 @@
|
||||||
# include "runtime/perfMemory.hpp"
|
# include "runtime/perfMemory.hpp"
|
||||||
# include "runtime/prefetch.hpp"
|
# include "runtime/prefetch.hpp"
|
||||||
# include "runtime/reflection.hpp"
|
# include "runtime/reflection.hpp"
|
||||||
# include "runtime/reflectionCompat.hpp"
|
|
||||||
# include "runtime/reflectionUtils.hpp"
|
# include "runtime/reflectionUtils.hpp"
|
||||||
# include "runtime/registerMap.hpp"
|
# include "runtime/registerMap.hpp"
|
||||||
# include "runtime/safepoint.hpp"
|
# include "runtime/safepoint.hpp"
|
||||||
|
|
|
@ -4020,249 +4020,6 @@ JVM_END
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Support for old native code-based reflection (pre-JDK 1.4)
|
|
||||||
// Disabled by default in the product build.
|
|
||||||
//
|
|
||||||
// See reflection.hpp for information on SUPPORT_OLD_REFLECTION
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#ifdef SUPPORT_OLD_REFLECTION
|
|
||||||
|
|
||||||
JVM_ENTRY(jobjectArray, JVM_GetClassFields(JNIEnv *env, jclass cls, jint which))
|
|
||||||
JVMWrapper("JVM_GetClassFields");
|
|
||||||
JvmtiVMObjectAllocEventCollector oam;
|
|
||||||
oop mirror = JNIHandles::resolve_non_null(cls);
|
|
||||||
objArrayOop result = Reflection::reflect_fields(mirror, which, CHECK_NULL);
|
|
||||||
return (jobjectArray) JNIHandles::make_local(env, result);
|
|
||||||
JVM_END
|
|
||||||
|
|
||||||
|
|
||||||
JVM_ENTRY(jobjectArray, JVM_GetClassMethods(JNIEnv *env, jclass cls, jint which))
|
|
||||||
JVMWrapper("JVM_GetClassMethods");
|
|
||||||
JvmtiVMObjectAllocEventCollector oam;
|
|
||||||
oop mirror = JNIHandles::resolve_non_null(cls);
|
|
||||||
objArrayOop result = Reflection::reflect_methods(mirror, which, CHECK_NULL);
|
|
||||||
//%note jvm_r4
|
|
||||||
return (jobjectArray) JNIHandles::make_local(env, result);
|
|
||||||
JVM_END
|
|
||||||
|
|
||||||
|
|
||||||
JVM_ENTRY(jobjectArray, JVM_GetClassConstructors(JNIEnv *env, jclass cls, jint which))
|
|
||||||
JVMWrapper("JVM_GetClassConstructors");
|
|
||||||
JvmtiVMObjectAllocEventCollector oam;
|
|
||||||
oop mirror = JNIHandles::resolve_non_null(cls);
|
|
||||||
objArrayOop result = Reflection::reflect_constructors(mirror, which, CHECK_NULL);
|
|
||||||
//%note jvm_r4
|
|
||||||
return (jobjectArray) JNIHandles::make_local(env, result);
|
|
||||||
JVM_END
|
|
||||||
|
|
||||||
|
|
||||||
JVM_ENTRY(jobject, JVM_GetClassField(JNIEnv *env, jclass cls, jstring name, jint which))
|
|
||||||
JVMWrapper("JVM_GetClassField");
|
|
||||||
JvmtiVMObjectAllocEventCollector oam;
|
|
||||||
if (name == NULL) return NULL;
|
|
||||||
Handle str (THREAD, JNIHandles::resolve_non_null(name));
|
|
||||||
|
|
||||||
const char* cstr = java_lang_String::as_utf8_string(str());
|
|
||||||
TempNewSymbol field_name = SymbolTable::probe(cstr, (int)strlen(cstr));
|
|
||||||
if (field_name == NULL) {
|
|
||||||
THROW_0(vmSymbols::java_lang_NoSuchFieldException());
|
|
||||||
}
|
|
||||||
|
|
||||||
oop mirror = JNIHandles::resolve_non_null(cls);
|
|
||||||
oop result = Reflection::reflect_field(mirror, field_name, which, CHECK_NULL);
|
|
||||||
if (result == NULL) {
|
|
||||||
THROW_0(vmSymbols::java_lang_NoSuchFieldException());
|
|
||||||
}
|
|
||||||
return JNIHandles::make_local(env, result);
|
|
||||||
JVM_END
|
|
||||||
|
|
||||||
|
|
||||||
JVM_ENTRY(jobject, JVM_GetClassMethod(JNIEnv *env, jclass cls, jstring name, jobjectArray types, jint which))
|
|
||||||
JVMWrapper("JVM_GetClassMethod");
|
|
||||||
JvmtiVMObjectAllocEventCollector oam;
|
|
||||||
if (name == NULL) {
|
|
||||||
THROW_0(vmSymbols::java_lang_NullPointerException());
|
|
||||||
}
|
|
||||||
Handle str (THREAD, JNIHandles::resolve_non_null(name));
|
|
||||||
|
|
||||||
const char* cstr = java_lang_String::as_utf8_string(str());
|
|
||||||
TempNewSymbol method_name = SymbolTable::probe(cstr, (int)strlen(cstr));
|
|
||||||
if (method_name == NULL) {
|
|
||||||
THROW_0(vmSymbols::java_lang_NoSuchMethodException());
|
|
||||||
}
|
|
||||||
|
|
||||||
oop mirror = JNIHandles::resolve_non_null(cls);
|
|
||||||
objArrayHandle tarray (THREAD, objArrayOop(JNIHandles::resolve(types)));
|
|
||||||
oop result = Reflection::reflect_method(mirror, method_name, tarray,
|
|
||||||
which, CHECK_NULL);
|
|
||||||
if (result == NULL) {
|
|
||||||
THROW_0(vmSymbols::java_lang_NoSuchMethodException());
|
|
||||||
}
|
|
||||||
return JNIHandles::make_local(env, result);
|
|
||||||
JVM_END
|
|
||||||
|
|
||||||
|
|
||||||
JVM_ENTRY(jobject, JVM_GetClassConstructor(JNIEnv *env, jclass cls, jobjectArray types, jint which))
|
|
||||||
JVMWrapper("JVM_GetClassConstructor");
|
|
||||||
JvmtiVMObjectAllocEventCollector oam;
|
|
||||||
oop mirror = JNIHandles::resolve_non_null(cls);
|
|
||||||
objArrayHandle tarray (THREAD, objArrayOop(JNIHandles::resolve(types)));
|
|
||||||
oop result = Reflection::reflect_constructor(mirror, tarray, which, CHECK_NULL);
|
|
||||||
if (result == NULL) {
|
|
||||||
THROW_0(vmSymbols::java_lang_NoSuchMethodException());
|
|
||||||
}
|
|
||||||
return (jobject) JNIHandles::make_local(env, result);
|
|
||||||
JVM_END
|
|
||||||
|
|
||||||
|
|
||||||
// Instantiation ///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
JVM_ENTRY(jobject, JVM_NewInstance(JNIEnv *env, jclass cls))
|
|
||||||
JVMWrapper("JVM_NewInstance");
|
|
||||||
Handle mirror(THREAD, JNIHandles::resolve_non_null(cls));
|
|
||||||
|
|
||||||
methodOop resolved_constructor = java_lang_Class::resolved_constructor(mirror());
|
|
||||||
if (resolved_constructor == NULL) {
|
|
||||||
klassOop k = java_lang_Class::as_klassOop(mirror());
|
|
||||||
// The java.lang.Class object caches a resolved constructor if all the checks
|
|
||||||
// below were done successfully and a constructor was found.
|
|
||||||
|
|
||||||
// Do class based checks
|
|
||||||
if (java_lang_Class::is_primitive(mirror())) {
|
|
||||||
const char* msg = "";
|
|
||||||
if (mirror == Universe::bool_mirror()) msg = "java/lang/Boolean";
|
|
||||||
else if (mirror == Universe::char_mirror()) msg = "java/lang/Character";
|
|
||||||
else if (mirror == Universe::float_mirror()) msg = "java/lang/Float";
|
|
||||||
else if (mirror == Universe::double_mirror()) msg = "java/lang/Double";
|
|
||||||
else if (mirror == Universe::byte_mirror()) msg = "java/lang/Byte";
|
|
||||||
else if (mirror == Universe::short_mirror()) msg = "java/lang/Short";
|
|
||||||
else if (mirror == Universe::int_mirror()) msg = "java/lang/Integer";
|
|
||||||
else if (mirror == Universe::long_mirror()) msg = "java/lang/Long";
|
|
||||||
THROW_MSG_0(vmSymbols::java_lang_NullPointerException(), msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check whether we are allowed to instantiate this class
|
|
||||||
Klass::cast(k)->check_valid_for_instantiation(false, CHECK_NULL); // Array classes get caught here
|
|
||||||
instanceKlassHandle klass(THREAD, k);
|
|
||||||
// Make sure class is initialized (also so all methods are rewritten)
|
|
||||||
klass->initialize(CHECK_NULL);
|
|
||||||
|
|
||||||
// Lookup default constructor
|
|
||||||
resolved_constructor = klass->find_method(vmSymbols::object_initializer_name(), vmSymbols::void_method_signature());
|
|
||||||
if (resolved_constructor == NULL) {
|
|
||||||
ResourceMark rm(THREAD);
|
|
||||||
THROW_MSG_0(vmSymbols::java_lang_InstantiationException(), klass->external_name());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cache result in java.lang.Class object. Does not have to be MT safe.
|
|
||||||
java_lang_Class::set_resolved_constructor(mirror(), resolved_constructor);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(resolved_constructor != NULL, "sanity check");
|
|
||||||
methodHandle constructor = methodHandle(THREAD, resolved_constructor);
|
|
||||||
|
|
||||||
// We have an initialized instanceKlass with a default constructor
|
|
||||||
instanceKlassHandle klass(THREAD, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)));
|
|
||||||
assert(klass->is_initialized() || klass->is_being_initialized(), "sanity check");
|
|
||||||
|
|
||||||
// Do security check
|
|
||||||
klassOop caller_klass = NULL;
|
|
||||||
if (UsePrivilegedStack) {
|
|
||||||
caller_klass = thread->security_get_caller_class(2);
|
|
||||||
|
|
||||||
if (!Reflection::verify_class_access(caller_klass, klass(), false) ||
|
|
||||||
!Reflection::verify_field_access(caller_klass,
|
|
||||||
klass(),
|
|
||||||
klass(),
|
|
||||||
constructor->access_flags(),
|
|
||||||
false,
|
|
||||||
true)) {
|
|
||||||
ResourceMark rm(THREAD);
|
|
||||||
THROW_MSG_0(vmSymbols::java_lang_IllegalAccessException(), klass->external_name());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allocate object and call constructor
|
|
||||||
Handle receiver = klass->allocate_instance_handle(CHECK_NULL);
|
|
||||||
JavaCalls::call_default_constructor(thread, constructor, receiver, CHECK_NULL);
|
|
||||||
|
|
||||||
jobject res = JNIHandles::make_local(env, receiver());
|
|
||||||
if (JvmtiExport::should_post_vm_object_alloc()) {
|
|
||||||
JvmtiExport::post_vm_object_alloc(JavaThread::current(), receiver());
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
JVM_END
|
|
||||||
|
|
||||||
|
|
||||||
// Field ////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
JVM_ENTRY(jobject, JVM_GetField(JNIEnv *env, jobject field, jobject obj))
|
|
||||||
JVMWrapper("JVM_GetField");
|
|
||||||
JvmtiVMObjectAllocEventCollector oam;
|
|
||||||
Handle field_mirror(thread, JNIHandles::resolve(field));
|
|
||||||
Handle receiver (thread, JNIHandles::resolve(obj));
|
|
||||||
fieldDescriptor fd;
|
|
||||||
Reflection::resolve_field(field_mirror, receiver, &fd, false, CHECK_NULL);
|
|
||||||
jvalue value;
|
|
||||||
BasicType type = Reflection::field_get(&value, &fd, receiver);
|
|
||||||
oop box = Reflection::box(&value, type, CHECK_NULL);
|
|
||||||
return JNIHandles::make_local(env, box);
|
|
||||||
JVM_END
|
|
||||||
|
|
||||||
|
|
||||||
JVM_ENTRY(jvalue, JVM_GetPrimitiveField(JNIEnv *env, jobject field, jobject obj, unsigned char wCode))
|
|
||||||
JVMWrapper("JVM_GetPrimitiveField");
|
|
||||||
Handle field_mirror(thread, JNIHandles::resolve(field));
|
|
||||||
Handle receiver (thread, JNIHandles::resolve(obj));
|
|
||||||
fieldDescriptor fd;
|
|
||||||
jvalue value;
|
|
||||||
value.j = 0;
|
|
||||||
Reflection::resolve_field(field_mirror, receiver, &fd, false, CHECK_(value));
|
|
||||||
BasicType type = Reflection::field_get(&value, &fd, receiver);
|
|
||||||
BasicType wide_type = (BasicType) wCode;
|
|
||||||
if (type != wide_type) {
|
|
||||||
Reflection::widen(&value, type, wide_type, CHECK_(value));
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
JVM_END // should really be JVM_END, but that doesn't work for union types!
|
|
||||||
|
|
||||||
|
|
||||||
JVM_ENTRY(void, JVM_SetField(JNIEnv *env, jobject field, jobject obj, jobject val))
|
|
||||||
JVMWrapper("JVM_SetField");
|
|
||||||
Handle field_mirror(thread, JNIHandles::resolve(field));
|
|
||||||
Handle receiver (thread, JNIHandles::resolve(obj));
|
|
||||||
oop box = JNIHandles::resolve(val);
|
|
||||||
fieldDescriptor fd;
|
|
||||||
Reflection::resolve_field(field_mirror, receiver, &fd, true, CHECK);
|
|
||||||
BasicType field_type = fd.field_type();
|
|
||||||
jvalue value;
|
|
||||||
BasicType value_type;
|
|
||||||
if (field_type == T_OBJECT || field_type == T_ARRAY) {
|
|
||||||
// Make sure we do no unbox e.g. java/lang/Integer instances when storing into an object array
|
|
||||||
value_type = Reflection::unbox_for_regular_object(box, &value);
|
|
||||||
Reflection::field_set(&value, &fd, receiver, field_type, CHECK);
|
|
||||||
} else {
|
|
||||||
value_type = Reflection::unbox_for_primitive(box, &value, CHECK);
|
|
||||||
Reflection::field_set(&value, &fd, receiver, value_type, CHECK);
|
|
||||||
}
|
|
||||||
JVM_END
|
|
||||||
|
|
||||||
|
|
||||||
JVM_ENTRY(void, JVM_SetPrimitiveField(JNIEnv *env, jobject field, jobject obj, jvalue v, unsigned char vCode))
|
|
||||||
JVMWrapper("JVM_SetPrimitiveField");
|
|
||||||
Handle field_mirror(thread, JNIHandles::resolve(field));
|
|
||||||
Handle receiver (thread, JNIHandles::resolve(obj));
|
|
||||||
fieldDescriptor fd;
|
|
||||||
Reflection::resolve_field(field_mirror, receiver, &fd, true, CHECK);
|
|
||||||
BasicType value_type = (BasicType) vCode;
|
|
||||||
Reflection::field_set(&v, &fd, receiver, value_type, CHECK);
|
|
||||||
JVM_END
|
|
||||||
|
|
||||||
|
|
||||||
// Method ///////////////////////////////////////////////////////////////////////////////////////////
|
// Method ///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
JVM_ENTRY(jobject, JVM_InvokeMethod(JNIEnv *env, jobject method, jobject obj, jobjectArray args0))
|
JVM_ENTRY(jobject, JVM_InvokeMethod(JNIEnv *env, jobject method, jobject obj, jobjectArray args0))
|
||||||
|
@ -4302,8 +4059,6 @@ JVM_ENTRY(jobject, JVM_NewInstanceFromConstructor(JNIEnv *env, jobject c, jobjec
|
||||||
return res;
|
return res;
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
#endif /* SUPPORT_OLD_REFLECTION */
|
|
||||||
|
|
||||||
// Atomic ///////////////////////////////////////////////////////////////////////////////////////////
|
// Atomic ///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
JVM_LEAF(jboolean, JVM_SupportsCX8())
|
JVM_LEAF(jboolean, JVM_SupportsCX8())
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
#define SHARE_VM_PRIMS_JVM_H
|
#define SHARE_VM_PRIMS_JVM_H
|
||||||
|
|
||||||
#include "prims/jni.h"
|
#include "prims/jni.h"
|
||||||
#include "runtime/reflectionCompat.hpp"
|
|
||||||
#ifdef TARGET_OS_FAMILY_linux
|
#ifdef TARGET_OS_FAMILY_linux
|
||||||
# include "jvm_linux.h"
|
# include "jvm_linux.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -43,8 +42,7 @@
|
||||||
// HotSpot integration note:
|
// HotSpot integration note:
|
||||||
//
|
//
|
||||||
// This file and jvm.h used with the JDK are identical,
|
// This file and jvm.h used with the JDK are identical,
|
||||||
// except for the three includes removed below and the
|
// except for the three includes removed below
|
||||||
// SUPPORT_OLD_REFLECTION sections cut out of the JDK's jvm.h.
|
|
||||||
|
|
||||||
// #include <sys/stat.h>
|
// #include <sys/stat.h>
|
||||||
// #include "jni.h"
|
// #include "jni.h"
|
||||||
|
@ -443,14 +441,6 @@ JVM_DefineClassWithSourceCond(JNIEnv *env, const char *name,
|
||||||
jsize len, jobject pd, const char *source,
|
jsize len, jobject pd, const char *source,
|
||||||
jboolean verify);
|
jboolean verify);
|
||||||
|
|
||||||
/* Define a class with a source (MLVM) */
|
|
||||||
JNIEXPORT jclass JNICALL
|
|
||||||
JVM_DefineClassWithCP(JNIEnv *env, const char *name, jobject loader,
|
|
||||||
const jbyte *buf, jsize len, jobject pd,
|
|
||||||
const char *source,
|
|
||||||
// same args as JVM_DefineClassWithSource to this point
|
|
||||||
jobjectArray constants);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reflection support functions
|
* Reflection support functions
|
||||||
*/
|
*/
|
||||||
|
@ -1442,65 +1432,6 @@ JVM_RawMonitorEnter(void *mon);
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
JVM_RawMonitorExit(void *mon);
|
JVM_RawMonitorExit(void *mon);
|
||||||
|
|
||||||
|
|
||||||
#ifdef SUPPORT_OLD_REFLECTION
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Support for old native code-based (pre-JDK 1.4) reflection implementation.
|
|
||||||
* Disabled by default in the product build.
|
|
||||||
*
|
|
||||||
* See reflection.hpp for information on SUPPORT_OLD_REFLECTION
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* reflecting fields and methods.
|
|
||||||
* which: 0 --- MEMBER_PUBLIC
|
|
||||||
* 1 --- MEMBER_DECLARED
|
|
||||||
* NOTE: absent in product build by default
|
|
||||||
*/
|
|
||||||
|
|
||||||
JNIEXPORT jobjectArray JNICALL
|
|
||||||
JVM_GetClassFields(JNIEnv *env, jclass cls, jint which);
|
|
||||||
|
|
||||||
JNIEXPORT jobjectArray JNICALL
|
|
||||||
JVM_GetClassMethods(JNIEnv *env, jclass cls, jint which);
|
|
||||||
|
|
||||||
JNIEXPORT jobjectArray JNICALL
|
|
||||||
JVM_GetClassConstructors(JNIEnv *env, jclass cls, jint which);
|
|
||||||
|
|
||||||
JNIEXPORT jobject JNICALL
|
|
||||||
JVM_GetClassField(JNIEnv *env, jclass cls, jstring name, jint which);
|
|
||||||
|
|
||||||
JNIEXPORT jobject JNICALL
|
|
||||||
JVM_GetClassMethod(JNIEnv *env, jclass cls, jstring name, jobjectArray types,
|
|
||||||
jint which);
|
|
||||||
JNIEXPORT jobject JNICALL
|
|
||||||
JVM_GetClassConstructor(JNIEnv *env, jclass cls, jobjectArray types,
|
|
||||||
jint which);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Implements Class.newInstance
|
|
||||||
*/
|
|
||||||
JNIEXPORT jobject JNICALL
|
|
||||||
JVM_NewInstance(JNIEnv *env, jclass cls);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* java.lang.reflect.Field
|
|
||||||
*/
|
|
||||||
JNIEXPORT jobject JNICALL
|
|
||||||
JVM_GetField(JNIEnv *env, jobject field, jobject obj);
|
|
||||||
|
|
||||||
JNIEXPORT jvalue JNICALL
|
|
||||||
JVM_GetPrimitiveField(JNIEnv *env, jobject field, jobject obj,
|
|
||||||
unsigned char wCode);
|
|
||||||
|
|
||||||
JNIEXPORT void JNICALL
|
|
||||||
JVM_SetField(JNIEnv *env, jobject field, jobject obj, jobject val);
|
|
||||||
|
|
||||||
JNIEXPORT void JNICALL
|
|
||||||
JVM_SetPrimitiveField(JNIEnv *env, jobject field, jobject obj, jvalue v,
|
|
||||||
unsigned char vCode);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* java.lang.reflect.Method
|
* java.lang.reflect.Method
|
||||||
*/
|
*/
|
||||||
|
@ -1513,8 +1444,6 @@ JVM_InvokeMethod(JNIEnv *env, jobject method, jobject obj, jobjectArray args0);
|
||||||
JNIEXPORT jobject JNICALL
|
JNIEXPORT jobject JNICALL
|
||||||
JVM_NewInstanceFromConstructor(JNIEnv *env, jobject c, jobjectArray args0);
|
JVM_NewInstanceFromConstructor(JNIEnv *env, jobject c, jobjectArray args0);
|
||||||
|
|
||||||
#endif /* SUPPORT_OLD_REFLECTION */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* java.lang.management support
|
* java.lang.management support
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -33,7 +33,6 @@
|
||||||
#include "runtime/globals.hpp"
|
#include "runtime/globals.hpp"
|
||||||
#include "runtime/interfaceSupport.hpp"
|
#include "runtime/interfaceSupport.hpp"
|
||||||
#include "runtime/reflection.hpp"
|
#include "runtime/reflection.hpp"
|
||||||
#include "runtime/reflectionCompat.hpp"
|
|
||||||
#include "runtime/synchronizer.hpp"
|
#include "runtime/synchronizer.hpp"
|
||||||
#include "services/threadService.hpp"
|
#include "services/threadService.hpp"
|
||||||
#include "utilities/copy.hpp"
|
#include "utilities/copy.hpp"
|
||||||
|
|
|
@ -844,16 +844,6 @@ oop Reflection::new_field(fieldDescriptor* fd, bool intern_name, TRAPS) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Supporting routines for old native code-based reflection (pre-JDK 1.4).
|
|
||||||
//
|
|
||||||
// See reflection.hpp for details.
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#ifdef SUPPORT_OLD_REFLECTION
|
|
||||||
|
|
||||||
methodHandle Reflection::resolve_interface_call(instanceKlassHandle klass, methodHandle method,
|
methodHandle Reflection::resolve_interface_call(instanceKlassHandle klass, methodHandle method,
|
||||||
KlassHandle recv_klass, Handle receiver, TRAPS) {
|
KlassHandle recv_klass, Handle receiver, TRAPS) {
|
||||||
assert(!method.is_null() , "method should not be null");
|
assert(!method.is_null() , "method should not be null");
|
||||||
|
@ -1081,519 +1071,6 @@ BasicType Reflection::basic_type_mirror_to_basic_type(oop basic_type_mirror, TRA
|
||||||
return java_lang_Class::primitive_type(basic_type_mirror);
|
return java_lang_Class::primitive_type(basic_type_mirror);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Reflection::match_parameter_types(methodHandle method, objArrayHandle types, int parameter_count, TRAPS) {
|
|
||||||
int types_len = types.is_null() ? 0 : types->length();
|
|
||||||
if (types_len != parameter_count) return false;
|
|
||||||
if (parameter_count > 0) {
|
|
||||||
objArrayHandle method_types = get_parameter_types(method, parameter_count, NULL, CHECK_false);
|
|
||||||
for (int index = 0; index < parameter_count; index++) {
|
|
||||||
if (types->obj_at(index) != method_types->obj_at(index)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
oop Reflection::new_field(FieldStream* st, TRAPS) {
|
|
||||||
Symbol* field_name = st->name();
|
|
||||||
Handle name = java_lang_String::create_from_symbol(field_name, CHECK_NULL);
|
|
||||||
Symbol* signature = st->signature();
|
|
||||||
Handle type = new_type(signature, st->klass(), CHECK_NULL);
|
|
||||||
Handle rh = java_lang_reflect_Field::create(CHECK_NULL);
|
|
||||||
oop result = rh();
|
|
||||||
|
|
||||||
java_lang_reflect_Field::set_clazz(result, st->klass()->java_mirror());
|
|
||||||
java_lang_reflect_Field::set_slot(result, st->index());
|
|
||||||
java_lang_reflect_Field::set_name(result, name());
|
|
||||||
java_lang_reflect_Field::set_type(result, type());
|
|
||||||
// Note the ACC_ANNOTATION bit, which is a per-class access flag, is never set here.
|
|
||||||
java_lang_reflect_Field::set_modifiers(result, st->access_flags().as_int() & JVM_RECOGNIZED_FIELD_MODIFIERS);
|
|
||||||
java_lang_reflect_Field::set_override(result, false);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool Reflection::resolve_field(Handle field_mirror, Handle& receiver, fieldDescriptor* fd, bool check_final, TRAPS) {
|
|
||||||
if (field_mirror.is_null()) {
|
|
||||||
THROW_(vmSymbols::java_lang_NullPointerException(), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
instanceKlassHandle klass (THREAD, java_lang_Class::as_klassOop(java_lang_reflect_Field::clazz(field_mirror())));
|
|
||||||
int slot = java_lang_reflect_Field::slot(field_mirror());
|
|
||||||
|
|
||||||
// Ensure klass is initialized
|
|
||||||
klass->initialize(CHECK_false);
|
|
||||||
fd->initialize(klass(), slot);
|
|
||||||
|
|
||||||
bool is_static = fd->is_static();
|
|
||||||
KlassHandle receiver_klass;
|
|
||||||
|
|
||||||
if (is_static) {
|
|
||||||
receiver = KlassHandle(THREAD, klass());
|
|
||||||
receiver_klass = klass;
|
|
||||||
} else {
|
|
||||||
// Check object is a non-null instance of declaring class
|
|
||||||
if (receiver.is_null()) {
|
|
||||||
THROW_(vmSymbols::java_lang_NullPointerException(), false);
|
|
||||||
}
|
|
||||||
if (!receiver->is_a(klass())) {
|
|
||||||
THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), "object is not an instance of declaring class", false);
|
|
||||||
}
|
|
||||||
receiver_klass = KlassHandle(THREAD, receiver->klass());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Access checking (unless overridden by Field)
|
|
||||||
if (!java_lang_reflect_Field::override(field_mirror())) {
|
|
||||||
if (!(klass->is_public() && fd->is_public())) {
|
|
||||||
bool access_check = reflect_check_access(klass(), fd->access_flags(), receiver_klass(), false, CHECK_false);
|
|
||||||
if (!access_check) {
|
|
||||||
return false; // exception
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (check_final && fd->is_final()) {
|
|
||||||
// In 1.3 we always throw an error when attempting to set a final field.
|
|
||||||
// In 1.2.x, this was allowed in the override bit was set by calling Field.setAccessible(true).
|
|
||||||
// We currently maintain backwards compatibility. See bug 4250960.
|
|
||||||
bool strict_final_check = !JDK_Version::is_jdk12x_version();
|
|
||||||
if (strict_final_check || !java_lang_reflect_Field::override(field_mirror())) {
|
|
||||||
THROW_MSG_(vmSymbols::java_lang_IllegalAccessException(), "field is final", false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BasicType Reflection::field_get(jvalue* value, fieldDescriptor* fd, Handle receiver) {
|
|
||||||
BasicType field_type = fd->field_type();
|
|
||||||
int offset = fd->offset();
|
|
||||||
switch (field_type) {
|
|
||||||
case T_BOOLEAN:
|
|
||||||
value->z = receiver->bool_field(offset);
|
|
||||||
break;
|
|
||||||
case T_CHAR:
|
|
||||||
value->c = receiver->char_field(offset);
|
|
||||||
break;
|
|
||||||
case T_FLOAT:
|
|
||||||
value->f = receiver->float_field(offset);
|
|
||||||
break;
|
|
||||||
case T_DOUBLE:
|
|
||||||
value->d = receiver->double_field(offset);
|
|
||||||
break;
|
|
||||||
case T_BYTE:
|
|
||||||
value->b = receiver->byte_field(offset);
|
|
||||||
break;
|
|
||||||
case T_SHORT:
|
|
||||||
value->s = receiver->short_field(offset);
|
|
||||||
break;
|
|
||||||
case T_INT:
|
|
||||||
value->i = receiver->int_field(offset);
|
|
||||||
break;
|
|
||||||
case T_LONG:
|
|
||||||
value->j = receiver->long_field(offset);
|
|
||||||
break;
|
|
||||||
case T_OBJECT:
|
|
||||||
case T_ARRAY:
|
|
||||||
value->l = (jobject) receiver->obj_field(offset);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return T_ILLEGAL;
|
|
||||||
}
|
|
||||||
return field_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Reflection::field_set(jvalue* value, fieldDescriptor* fd, Handle receiver, BasicType value_type, TRAPS) {
|
|
||||||
BasicType field_type = fd->field_type();
|
|
||||||
if (field_type != value_type) {
|
|
||||||
widen(value, value_type, field_type, CHECK);
|
|
||||||
}
|
|
||||||
|
|
||||||
int offset = fd->offset();
|
|
||||||
switch (field_type) {
|
|
||||||
case T_BOOLEAN:
|
|
||||||
receiver->bool_field_put(offset, value->z);
|
|
||||||
break;
|
|
||||||
case T_CHAR:
|
|
||||||
receiver->char_field_put(offset, value->c);
|
|
||||||
break;
|
|
||||||
case T_FLOAT:
|
|
||||||
receiver->float_field_put(offset, value->f);
|
|
||||||
break;
|
|
||||||
case T_DOUBLE:
|
|
||||||
receiver->double_field_put(offset, value->d);
|
|
||||||
break;
|
|
||||||
case T_BYTE:
|
|
||||||
receiver->byte_field_put(offset, value->b);
|
|
||||||
break;
|
|
||||||
case T_SHORT:
|
|
||||||
receiver->short_field_put(offset, value->s);
|
|
||||||
break;
|
|
||||||
case T_INT:
|
|
||||||
receiver->int_field_put(offset, value->i);
|
|
||||||
break;
|
|
||||||
case T_LONG:
|
|
||||||
receiver->long_field_put(offset, value->j);
|
|
||||||
break;
|
|
||||||
case T_OBJECT:
|
|
||||||
case T_ARRAY: {
|
|
||||||
Handle obj(THREAD, (oop) value->l);
|
|
||||||
if (obj.not_null()) {
|
|
||||||
Symbol* signature = fd->signature();
|
|
||||||
Handle loader (THREAD, fd->loader());
|
|
||||||
Handle protect (THREAD, Klass::cast(fd->field_holder())->protection_domain());
|
|
||||||
klassOop k = SystemDictionary::resolve_or_fail(signature, loader, protect, true, CHECK); // may block
|
|
||||||
if (!obj->is_a(k)) {
|
|
||||||
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "field type mismatch");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
receiver->obj_field_put(offset, obj());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "field type mismatch");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
oop Reflection::reflect_field(oop mirror, Symbol* field_name, jint which, TRAPS) {
|
|
||||||
// Exclude primitive types and array types
|
|
||||||
if (java_lang_Class::is_primitive(mirror)) return NULL;
|
|
||||||
if (Klass::cast(java_lang_Class::as_klassOop(mirror))->oop_is_array()) return NULL;
|
|
||||||
|
|
||||||
instanceKlassHandle k(THREAD, java_lang_Class::as_klassOop(mirror));
|
|
||||||
bool local_fields_only = (which == DECLARED);
|
|
||||||
|
|
||||||
// Ensure class is linked
|
|
||||||
k->link_class(CHECK_NULL);
|
|
||||||
|
|
||||||
// Search class and interface fields
|
|
||||||
for (FieldStream st(k, local_fields_only, false); !st.eos(); st.next()) {
|
|
||||||
if (st.name() == field_name) {
|
|
||||||
if (local_fields_only || st.access_flags().is_public()) {
|
|
||||||
return new_field(&st, THREAD);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
objArrayOop Reflection::reflect_fields(oop mirror, jint which, TRAPS) {
|
|
||||||
// Exclude primitive types and array types
|
|
||||||
if (java_lang_Class::is_primitive(mirror)
|
|
||||||
|| Klass::cast(java_lang_Class::as_klassOop(mirror))->oop_is_array()) {
|
|
||||||
Symbol* name = vmSymbols::java_lang_reflect_Field();
|
|
||||||
klassOop klass = SystemDictionary::resolve_or_fail(name, true, CHECK_NULL);
|
|
||||||
return oopFactory::new_objArray(klass, 0, CHECK_NULL); // Return empty array
|
|
||||||
}
|
|
||||||
|
|
||||||
instanceKlassHandle k(THREAD, java_lang_Class::as_klassOop(mirror));
|
|
||||||
|
|
||||||
// Ensure class is linked
|
|
||||||
k->link_class(CHECK_NULL);
|
|
||||||
|
|
||||||
bool local_fields_only = (which == DECLARED);
|
|
||||||
int count = 0;
|
|
||||||
{ // Compute fields count for class and interface fields
|
|
||||||
for (FieldStream st(k, local_fields_only, false); !st.eos(); st.next()) {
|
|
||||||
if (local_fields_only || st.access_flags().is_public()) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allocate result
|
|
||||||
Symbol* name = vmSymbols::java_lang_reflect_Field();
|
|
||||||
klassOop klass = SystemDictionary::resolve_or_fail(name, true, CHECK_NULL);
|
|
||||||
objArrayOop r = oopFactory::new_objArray(klass, count, CHECK_NULL);
|
|
||||||
objArrayHandle result (THREAD, r);
|
|
||||||
|
|
||||||
// Fill in results backwards
|
|
||||||
{
|
|
||||||
for (FieldStream st(k, local_fields_only, false); !st.eos(); st.next()) {
|
|
||||||
if (local_fields_only || st.access_flags().is_public()) {
|
|
||||||
oop field = new_field(&st, CHECK_NULL);
|
|
||||||
result->obj_at_put(--count, field);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert(count == 0, "just checking");
|
|
||||||
}
|
|
||||||
return result();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
oop Reflection::reflect_method(oop mirror, Symbol* method_name, objArrayHandle types, jint which, TRAPS) {
|
|
||||||
if (java_lang_Class::is_primitive(mirror)) return NULL;
|
|
||||||
klassOop klass = java_lang_Class::as_klassOop(mirror);
|
|
||||||
if (Klass::cast(klass)->oop_is_array() && which == MEMBER_DECLARED) return NULL;
|
|
||||||
|
|
||||||
if (Klass::cast(java_lang_Class::as_klassOop(mirror))->oop_is_array()) {
|
|
||||||
klass = SystemDictionary::Object_klass();
|
|
||||||
}
|
|
||||||
instanceKlassHandle h_k(THREAD, klass);
|
|
||||||
|
|
||||||
// Ensure klass is linked (need not be initialized)
|
|
||||||
h_k->link_class(CHECK_NULL);
|
|
||||||
|
|
||||||
// For interfaces include static initializers under jdk1.2.x (since classic does that)
|
|
||||||
bool include_clinit = JDK_Version::is_jdk12x_version() && h_k->is_interface();
|
|
||||||
|
|
||||||
switch (which) {
|
|
||||||
case MEMBER_PUBLIC:
|
|
||||||
// First the public non-static methods (works if method holder is an interface)
|
|
||||||
// Note that we can ignore checks for overridden methods, since we go up the hierarchy.
|
|
||||||
{
|
|
||||||
for (MethodStream st(h_k, false, false); !st.eos(); st.next()) {
|
|
||||||
methodHandle m(THREAD, st.method());
|
|
||||||
// For interfaces include static initializers since classic does that!
|
|
||||||
if (method_name == m->name() && (include_clinit || (m->is_public() && !m->is_static() && !m->is_initializer()))) {
|
|
||||||
Symbol* signature = m->signature();
|
|
||||||
bool parameter_match = match_parameter_types(m, types, ArgumentCount(signature).size(), CHECK_NULL);
|
|
||||||
if (parameter_match) {
|
|
||||||
return new_method(m, false, false, THREAD);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Then the public static methods (works if method holder is an interface)
|
|
||||||
{
|
|
||||||
for (MethodStream st(h_k, false, false); !st.eos(); st.next()) {
|
|
||||||
methodHandle m(THREAD, st.method());
|
|
||||||
if (method_name == m->name() && m->is_public() && m->is_static() && !m->is_initializer()) {
|
|
||||||
Symbol* signature = m->signature();
|
|
||||||
bool parameter_match = match_parameter_types(m, types, ArgumentCount(signature).size(), CHECK_NULL);
|
|
||||||
if (parameter_match) {
|
|
||||||
return new_method(m, false, false, THREAD);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MEMBER_DECLARED:
|
|
||||||
// All local methods
|
|
||||||
{
|
|
||||||
for (MethodStream st(h_k, true, true); !st.eos(); st.next()) {
|
|
||||||
methodHandle m(THREAD, st.method());
|
|
||||||
if (method_name == m->name() && !m->is_initializer()) {
|
|
||||||
Symbol* signature = m->signature();
|
|
||||||
bool parameter_match = match_parameter_types(m, types, ArgumentCount(signature).size(), CHECK_NULL);
|
|
||||||
if (parameter_match) {
|
|
||||||
return new_method(m, false, false, THREAD);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
objArrayOop Reflection::reflect_methods(oop mirror, jint which, TRAPS) {
|
|
||||||
// Exclude primitive types
|
|
||||||
if (java_lang_Class::is_primitive(mirror) ||
|
|
||||||
(Klass::cast(java_lang_Class::as_klassOop(mirror))->oop_is_array() && (which == MEMBER_DECLARED))) {
|
|
||||||
klassOop klass = SystemDictionary::reflect_Method_klass();
|
|
||||||
return oopFactory::new_objArray(klass, 0, CHECK_NULL); // Return empty array
|
|
||||||
}
|
|
||||||
|
|
||||||
klassOop klass = java_lang_Class::as_klassOop(mirror);
|
|
||||||
if (Klass::cast(java_lang_Class::as_klassOop(mirror))->oop_is_array()) {
|
|
||||||
klass = SystemDictionary::Object_klass();
|
|
||||||
}
|
|
||||||
instanceKlassHandle h_k(THREAD, klass);
|
|
||||||
|
|
||||||
// Ensure klass is linked (need not be initialized)
|
|
||||||
h_k->link_class(CHECK_NULL);
|
|
||||||
|
|
||||||
// We search the (super)interfaces only if h_k is an interface itself
|
|
||||||
bool is_interface = h_k->is_interface();
|
|
||||||
|
|
||||||
// For interfaces include static initializers under jdk1.2.x (since classic does that)
|
|
||||||
bool include_clinit = JDK_Version::is_jdk12x_version() && is_interface;
|
|
||||||
|
|
||||||
switch (which) {
|
|
||||||
case MEMBER_PUBLIC:
|
|
||||||
{
|
|
||||||
|
|
||||||
// Count public methods (non-static and static)
|
|
||||||
int count = 0;
|
|
||||||
{
|
|
||||||
for (MethodStream st(h_k, false, false); !st.eos(); st.next()) {
|
|
||||||
methodOop m = st.method();
|
|
||||||
// For interfaces include static initializers since classic does that!
|
|
||||||
if (include_clinit || (!m->is_initializer() && m->is_public() && !m->is_overridden_in(h_k()))) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allocate result
|
|
||||||
klassOop klass = SystemDictionary::reflect_Method_klass();
|
|
||||||
objArrayOop r = oopFactory::new_objArray(klass, count, CHECK_NULL);
|
|
||||||
objArrayHandle h_result (THREAD, r);
|
|
||||||
|
|
||||||
// Fill in results backwards
|
|
||||||
{
|
|
||||||
// First the non-static public methods
|
|
||||||
for (MethodStream st(h_k, false, false); !st.eos(); st.next()) {
|
|
||||||
methodHandle m (THREAD, st.method());
|
|
||||||
if (!m->is_static() && !m->is_initializer() && m->is_public() && !m->is_overridden_in(h_k())) {
|
|
||||||
oop method = new_method(m, false, false, CHECK_NULL);
|
|
||||||
if (method == NULL) {
|
|
||||||
return NULL;
|
|
||||||
} else {
|
|
||||||
h_result->obj_at_put(--count, method);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{
|
|
||||||
// Then the static public methods
|
|
||||||
for (MethodStream st(h_k, false, !is_interface); !st.eos(); st.next()) {
|
|
||||||
methodHandle m (THREAD, st.method());
|
|
||||||
if (m->is_static() && (include_clinit || (!m->is_initializer()) && m->is_public() && !m->is_overridden_in(h_k()))) {
|
|
||||||
oop method = new_method(m, false, false, CHECK_NULL);
|
|
||||||
if (method == NULL) {
|
|
||||||
return NULL;
|
|
||||||
} else {
|
|
||||||
h_result->obj_at_put(--count, method);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(count == 0, "just checking");
|
|
||||||
return h_result();
|
|
||||||
}
|
|
||||||
|
|
||||||
case MEMBER_DECLARED:
|
|
||||||
{
|
|
||||||
// Count all methods
|
|
||||||
int count = 0;
|
|
||||||
{
|
|
||||||
for (MethodStream st(h_k, true, !is_interface); !st.eos(); st.next()) {
|
|
||||||
methodOop m = st.method();
|
|
||||||
if (!m->is_initializer()) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Allocate result
|
|
||||||
klassOop klass = SystemDictionary::reflect_Method_klass();
|
|
||||||
objArrayOop r = oopFactory::new_objArray(klass, count, CHECK_NULL);
|
|
||||||
objArrayHandle h_result (THREAD, r);
|
|
||||||
|
|
||||||
// Fill in results backwards
|
|
||||||
{
|
|
||||||
for (MethodStream st(h_k, true, true); !st.eos(); st.next()) {
|
|
||||||
methodHandle m (THREAD, st.method());
|
|
||||||
if (!m->is_initializer()) {
|
|
||||||
oop method = new_method(m, false, false, CHECK_NULL);
|
|
||||||
if (method == NULL) {
|
|
||||||
return NULL;
|
|
||||||
} else {
|
|
||||||
h_result->obj_at_put(--count, method);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert(count == 0, "just checking");
|
|
||||||
return h_result();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ShouldNotReachHere();
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
oop Reflection::reflect_constructor(oop mirror, objArrayHandle types, jint which, TRAPS) {
|
|
||||||
|
|
||||||
// Exclude primitive, interface and array types
|
|
||||||
bool prim = java_lang_Class::is_primitive(mirror);
|
|
||||||
Klass* klass = prim ? NULL : Klass::cast(java_lang_Class::as_klassOop(mirror));
|
|
||||||
if (prim || klass->is_interface() || klass->oop_is_array()) return NULL;
|
|
||||||
|
|
||||||
// Must be instance klass
|
|
||||||
instanceKlassHandle h_k(THREAD, java_lang_Class::as_klassOop(mirror));
|
|
||||||
|
|
||||||
// Ensure klass is linked (need not be initialized)
|
|
||||||
h_k->link_class(CHECK_NULL);
|
|
||||||
|
|
||||||
bool local_only = (which == MEMBER_DECLARED);
|
|
||||||
for (MethodStream st(h_k, true, true); !st.eos(); st.next()) {
|
|
||||||
methodHandle m(THREAD, st.method());
|
|
||||||
if (m->name() == vmSymbols::object_initializer_name() && (local_only || m->is_public())) {
|
|
||||||
Symbol* signature = m->signature();
|
|
||||||
bool parameter_match = match_parameter_types(m, types, ArgumentCount(signature).size(), CHECK_NULL);
|
|
||||||
if (parameter_match) {
|
|
||||||
return new_constructor(m, THREAD);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
objArrayOop Reflection::reflect_constructors(oop mirror, jint which, TRAPS) {
|
|
||||||
// Exclude primitive, interface and array types
|
|
||||||
bool prim = java_lang_Class::is_primitive(mirror);
|
|
||||||
Klass* k = prim ? NULL : Klass::cast(java_lang_Class::as_klassOop(mirror));
|
|
||||||
if (prim || k->is_interface() || k->oop_is_array()) {
|
|
||||||
return oopFactory::new_objArray(SystemDictionary::reflect_Constructor_klass(), 0, CHECK_NULL); // Return empty array
|
|
||||||
}
|
|
||||||
|
|
||||||
// Must be instanceKlass at this point
|
|
||||||
instanceKlassHandle h_k(THREAD, java_lang_Class::as_klassOop(mirror));
|
|
||||||
|
|
||||||
// Ensure klass is linked (need not be initialized)
|
|
||||||
h_k->link_class(CHECK_NULL);
|
|
||||||
|
|
||||||
bool local_only = (which == MEMBER_DECLARED);
|
|
||||||
int count = 0;
|
|
||||||
{
|
|
||||||
for (MethodStream st(h_k, true, true); !st.eos(); st.next()) {
|
|
||||||
methodOop m = st.method();
|
|
||||||
if (m->name() == vmSymbols::object_initializer_name() && (local_only || m->is_public())) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allocate result
|
|
||||||
Symbol* name = vmSymbols::java_lang_reflect_Constructor();
|
|
||||||
klassOop klass = SystemDictionary::resolve_or_fail(name, true, CHECK_NULL);
|
|
||||||
objArrayOop r = oopFactory::new_objArray(klass, count, CHECK_NULL);
|
|
||||||
objArrayHandle h_result (THREAD, r);
|
|
||||||
|
|
||||||
// Fill in results backwards
|
|
||||||
{
|
|
||||||
for (MethodStream st(h_k, true, true); !st.eos(); st.next()) {
|
|
||||||
methodHandle m (THREAD, st.method());
|
|
||||||
if (m->name() == vmSymbols::object_initializer_name() && (local_only || m->is_public())) {
|
|
||||||
oop constr = new_constructor(m, CHECK_NULL);
|
|
||||||
if (constr == NULL) {
|
|
||||||
return NULL;
|
|
||||||
} else {
|
|
||||||
h_result->obj_at_put(--count, constr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert(count == 0, "just checking");
|
|
||||||
}
|
|
||||||
return h_result();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// This would be nicer if, say, java.lang.reflect.Method was a subclass
|
// This would be nicer if, say, java.lang.reflect.Method was a subclass
|
||||||
// of java.lang.reflect.Constructor
|
// of java.lang.reflect.Constructor
|
||||||
|
|
||||||
|
@ -1647,6 +1124,3 @@ oop Reflection::invoke_constructor(oop constructor_mirror, objArrayHandle args,
|
||||||
invoke(klass, method, receiver, override, ptypes, T_VOID, args, false, CHECK_NULL);
|
invoke(klass, method, receiver, override, ptypes, T_VOID, args, false, CHECK_NULL);
|
||||||
return receiver();
|
return receiver();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif /* SUPPORT_OLD_REFLECTION */
|
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
|
|
||||||
#include "oops/oop.hpp"
|
#include "oops/oop.hpp"
|
||||||
#include "runtime/fieldDescriptor.hpp"
|
#include "runtime/fieldDescriptor.hpp"
|
||||||
#include "runtime/reflectionCompat.hpp"
|
|
||||||
#include "utilities/accessFlags.hpp"
|
#include "utilities/accessFlags.hpp"
|
||||||
#include "utilities/growableArray.hpp"
|
#include "utilities/growableArray.hpp"
|
||||||
|
|
||||||
|
@ -120,16 +119,6 @@ class Reflection: public AllStatic {
|
||||||
// Create a java.lang.reflect.Field object based on a field descriptor
|
// Create a java.lang.reflect.Field object based on a field descriptor
|
||||||
static oop new_field(fieldDescriptor* fd, bool intern_name, TRAPS);
|
static oop new_field(fieldDescriptor* fd, bool intern_name, TRAPS);
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Support for old native code-based reflection (pre-JDK 1.4)
|
|
||||||
//
|
|
||||||
// NOTE: the method and constructor invocation code is still used
|
|
||||||
// for startup time reasons; see reflectionCompat.hpp.
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#ifdef SUPPORT_OLD_REFLECTION
|
|
||||||
private:
|
private:
|
||||||
// method resolution for invoke
|
// method resolution for invoke
|
||||||
static methodHandle resolve_interface_call(instanceKlassHandle klass, methodHandle method, KlassHandle recv_klass, Handle receiver, TRAPS);
|
static methodHandle resolve_interface_call(instanceKlassHandle klass, methodHandle method, KlassHandle recv_klass, Handle receiver, TRAPS);
|
||||||
|
@ -144,35 +133,11 @@ private:
|
||||||
// Conversion
|
// Conversion
|
||||||
static BasicType basic_type_mirror_to_basic_type(oop basic_type_mirror, TRAPS);
|
static BasicType basic_type_mirror_to_basic_type(oop basic_type_mirror, TRAPS);
|
||||||
|
|
||||||
static bool match_parameter_types(methodHandle method, objArrayHandle types, int parameter_count, TRAPS);
|
|
||||||
// Creating new java.lang.reflect.xxx wrappers
|
|
||||||
static oop new_field(FieldStream* st, TRAPS);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Field lookup and verification.
|
|
||||||
static bool resolve_field(Handle field_mirror, Handle& receiver, fieldDescriptor* fd, bool check_final, TRAPS);
|
|
||||||
|
|
||||||
// Reflective field access. Returns type code. Throws IllegalArgumentException.
|
|
||||||
static BasicType field_get(jvalue* value, fieldDescriptor* fd, Handle receiver);
|
|
||||||
static void field_set(jvalue* value, fieldDescriptor* fd, Handle receiver, BasicType value_type, TRAPS);
|
|
||||||
|
|
||||||
// Reflective lookup of fields. Returns java.lang.reflect.Field instances.
|
|
||||||
static oop reflect_field(oop mirror, Symbol* field_name, jint which, TRAPS);
|
|
||||||
static objArrayOop reflect_fields(oop mirror, jint which, TRAPS);
|
|
||||||
|
|
||||||
// Reflective lookup of methods. Returns java.lang.reflect.Method instances.
|
|
||||||
static oop reflect_method(oop mirror, Symbol* method_name, objArrayHandle types, jint which, TRAPS);
|
|
||||||
static objArrayOop reflect_methods(oop mirror, jint which, TRAPS);
|
|
||||||
|
|
||||||
// Reflective lookup of constructors. Returns java.lang.reflect.Constructor instances.
|
|
||||||
static oop reflect_constructor(oop mirror, objArrayHandle types, jint which, TRAPS);
|
|
||||||
static objArrayOop reflect_constructors(oop mirror, jint which, TRAPS);
|
|
||||||
|
|
||||||
// Method invokation through java.lang.reflect.Method
|
// Method invokation through java.lang.reflect.Method
|
||||||
static oop invoke_method(oop method_mirror, Handle receiver, objArrayHandle args, TRAPS);
|
static oop invoke_method(oop method_mirror, Handle receiver, objArrayHandle args, TRAPS);
|
||||||
// Method invokation through java.lang.reflect.Constructor
|
// Method invokation through java.lang.reflect.Constructor
|
||||||
static oop invoke_constructor(oop method_mirror, objArrayHandle args, TRAPS);
|
static oop invoke_constructor(oop method_mirror, objArrayHandle args, TRAPS);
|
||||||
#endif /* SUPPORT_OLD_REFLECTION */
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,47 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SHARE_VM_RUNTIME_REFLECTIONCOMPAT_HPP
|
|
||||||
#define SHARE_VM_RUNTIME_REFLECTIONCOMPAT_HPP
|
|
||||||
|
|
||||||
// During the development of the JDK 1.4 reflection implementation
|
|
||||||
// based on dynamic bytecode generation, it was hoped that the bulk of
|
|
||||||
// the native code for reflection could be removed. Unfortunately
|
|
||||||
// there is currently a significant cost associated with loading the
|
|
||||||
// stub classes which impacts startup time. Until this cost can be
|
|
||||||
// reduced, the JVM entry points JVM_InvokeMethod and
|
|
||||||
// JVM_NewInstanceFromConstructor are still needed; these and their
|
|
||||||
// dependents currently constitute the bulk of the native code for
|
|
||||||
// reflection. If this cost is reduced in the future, the
|
|
||||||
// NativeMethodAccessorImpl and NativeConstructorAccessorImpl classes
|
|
||||||
// can be removed from sun.reflect and all of the code guarded by this
|
|
||||||
// flag removed from the product build. (Non-product builds,
|
|
||||||
// specifically the "optimized" target, would retain the code so they
|
|
||||||
// could be dropped into earlier JDKs for comparative benchmarking.)
|
|
||||||
|
|
||||||
//#ifndef PRODUCT
|
|
||||||
# define SUPPORT_OLD_REFLECTION
|
|
||||||
//#endif
|
|
||||||
|
|
||||||
#endif // SHARE_VM_RUNTIME_REFLECTIONCOMPAT_HPP
|
|
Loading…
Add table
Add a link
Reference in a new issue