1 /* src/native/vm/reflection.cpp - helper functions for java/lang/reflect
3 Copyright (C) 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2, or (at
11 your option) any later version.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
30 #include "native/jni.h"
31 #include "native/llni.h"
32 #include "native/native.h"
34 #if defined(ENABLE_ANNOTATIONS) && defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
38 #include "native/vm/reflection.hpp"
40 #include "vm/access.h"
41 #include "vm/builtin.h"
42 #include "vm/exceptions.hpp"
43 #include "vm/global.h"
44 #include "vm/initialize.h"
45 #include "vm/string.hpp"
47 #include "vmcore/globals.hpp"
48 #include "vmcore/javaobjects.hpp"
49 #include "vmcore/method.h"
53 * Invoke a method on the given object with the given arguments.
55 * For instance methods OBJ must be != NULL and the method is looked up
56 * in the vftbl of the object.
58 * For static methods, OBJ is ignored.
60 java_handle_t* Reflection::invoke(methodinfo *m, java_handle_t *o, java_handle_objectarray_t *params)
71 argcount = m->parseddesc->paramcount;
72 paramcount = argcount;
74 /* If method is non-static, remove the `this' pointer. */
76 if (!(m->flags & ACC_STATIC))
79 /* For instance methods the object has to be an instance of the
80 class the method belongs to. For static methods the obj
81 parameter is ignored. */
83 if (!(m->flags & ACC_STATIC) && o && (!builtin_instanceof(o, m->clazz))) {
84 exceptions_throw_illegalargumentexception();
88 /* check if we got the right number of arguments */
90 if (((params == NULL) && (paramcount != 0)) ||
91 (params && (LLNI_array_size(params) != paramcount)))
93 exceptions_throw_illegalargumentexception();
97 /* for instance methods we need an object */
99 if (!(m->flags & ACC_STATIC) && (o == NULL)) {
100 /* XXX not sure if that is the correct exception */
101 exceptions_throw_nullpointerexception();
105 /* for static methods, zero object to make subsequent code simpler */
106 if (m->flags & ACC_STATIC)
110 /* for instance methods we must do a vftbl lookup */
111 resm = method_vftbl_lookup(LLNI_vftbl_direct(o), m);
114 /* for static methods, just for convenience */
118 ro = vm_call_method_objectarray(resm, o, params);
124 /* reflect_method_invoke *******************************************************
126 Invokes the given method.
129 m .......... methodinfo
130 args ....... method arguments
131 override ... override security checks
134 return value of the method
136 *******************************************************************************/
138 java_handle_t* Reflection::method_invoke(methodinfo *m, java_handle_t *o, java_handle_objectarray_t *args, bool override)
142 /* Should we bypass security the checks (AccessibleObject)? */
144 if (override == false) {
145 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
146 /* This method is always called like this:
147 [0] java.lang.reflect.Method.invokeNative (Native Method)
148 [1] java.lang.reflect.Method.invoke (Method.java:329)
152 if (!access_check_method(m, 2))
154 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
155 /* We only pass 1 here as stacktrace_get_caller_class, which
156 is called from access_check_method, skips
157 java.lang.reflect.Method.invoke(). */
159 if (!access_check_method(m, 1))
162 # error unknown classpath configuration
166 /* Check if method class is initialized. */
168 if (!(m->clazz->state & CLASS_INITIALIZED))
169 if (!initialize_class(m->clazz))
172 /* Call the Java method. */
174 ro = invoke(m, o, args);
180 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH) && defined(ENABLE_ANNOTATIONS)
181 /* reflect_get_declaredannotations *********************************************
183 Calls the annotation parser with the unparsed annotations and returnes
184 the parsed annotations as a map.
187 annotations........the unparsed annotations
188 declaringClass.....the class in which the annotated element is declared
189 referer............the calling class (for the 'referer' parameter of
193 The parsed annotations as a
194 java.util.Map<Class<? extends Annotation>, Annotation>.
196 *******************************************************************************/
198 java_handle_t* Reflection::get_declaredannotations(java_handle_bytearray_t *annotations, classinfo* declaringClass, classinfo *referer)
200 static methodinfo* m_parseAnnotations = NULL;
202 java_handle_t* h = native_new_and_init(class_sun_reflect_ConstantPool);
207 sun_reflect_ConstantPool cp(h);
208 cp.set_constantPoolOop(declaringClass);
210 /* only resolve the parser method the first time */
211 if (m_parseAnnotations == NULL) {
212 // FIXME Use globals.
213 utf* utf_parseAnnotations = utf_new_char("parseAnnotations");
214 utf* utf_desc = utf_new_char("([BLsun/reflect/ConstantPool;Ljava/lang/Class;)Ljava/util/Map;");
216 if (utf_parseAnnotations == NULL || utf_desc == NULL)
219 m_parseAnnotations = class_resolveclassmethod(
220 class_sun_reflect_annotation_AnnotationParser,
221 utf_parseAnnotations,
226 if (m_parseAnnotations == NULL)
230 return (java_handle_t*) vm_call_method(m_parseAnnotations, NULL, annotations, cp.get_handle(), declaringClass);
234 /* reflect_get_parameterannotations *******************************************
236 Calls the annotation parser with the unparsed parameter annotations of
237 a method and returnes the parsed parameter annotations in a 2 dimensional
241 parameterAnnotations....the unparsed parameter annotations
242 slot....................the slot of the method
243 declaringClass..........the class in which the annotated element is
245 referer.................the calling class (for the 'referer' parameter
249 The parsed parameter annotations in a 2 dimensional array.
251 *******************************************************************************/
253 java_handle_objectarray_t* Reflection::get_parameterannotations(java_handle_bytearray_t* parameterAnnotations, methodinfo* m, classinfo* referer)
255 /* This method in java would be basically the following.
256 * We don't do it in java because we don't want to make a
257 * public method with wich you can get a ConstantPool, because
258 * with that you could read any kind of constants (even private
261 * ConstantPool constPool = new ConstantPool();
262 * constPool.constantPoolOop = method.getDeclaringClass();
263 * return sun.reflect.AnnotationParser.parseParameterAnnotations(
264 * parameterAnnotations,
266 * method.getDeclaringClass(),
267 * method.getParameterTypes().length);
270 static methodinfo* m_parseParameterAnnotations = NULL;
272 /* get parameter count */
274 int32_t numParameters = method_get_parametercount(m);
276 if (numParameters < 0)
279 /* get ConstantPool */
281 java_handle_t* h = native_new_and_init(class_sun_reflect_ConstantPool);
286 sun_reflect_ConstantPool cp(h);
287 cp.set_constantPoolOop(m->clazz);
289 /* only resolve the parser method the first time */
290 if (m_parseParameterAnnotations == NULL) {
291 utf* utf_parseParameterAnnotations = utf_new_char("parseParameterAnnotations");
292 utf* utf_desc = utf_new_char("([BLsun/reflect/ConstantPool;Ljava/lang/Class;I)[[Ljava/lang/annotation/Annotation;");
294 if (utf_parseParameterAnnotations == NULL || utf_desc == NULL)
297 /* get parser method */
299 m_parseParameterAnnotations = class_resolveclassmethod(
300 class_sun_reflect_annotation_AnnotationParser,
301 utf_parseParameterAnnotations,
306 if (m_parseParameterAnnotations == NULL)
310 return (java_handle_objectarray_t*) vm_call_method(m_parseParameterAnnotations, NULL, parameterAnnotations, cp.get_handle(), m->clazz, numParameters);
316 * These are local overrides for various environment variables in Emacs.
317 * Please do not remove this and leave it at the end of the file, where
318 * Emacs will automagically detect them.
319 * ---------------------------------------------------------------------
322 * indent-tabs-mode: t
326 * vim:noexpandtab:sw=4:ts=4: