CACAO
reflection.cpp
Go to the documentation of this file.
1 /* src/native/vm/reflection.cpp - helper functions for java/lang/reflect
2 
3  Copyright (C) 1996-2013
4  CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5 
6  This file is part of CACAO.
7 
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.
12 
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.
17 
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
21  02110-1301, USA.
22 
23 */
24 
25 
26 #include "config.h"
27 
28 #include "native/llni.hpp"
29 #include "native/native.hpp"
30 
31 #if defined(ENABLE_ANNOTATIONS) && defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
32 # include "vm/vm.hpp"
33 #endif
34 
35 #include "native/vm/reflection.hpp"
36 
37 #include "vm/access.hpp"
38 #include "vm/array.hpp"
39 #include "vm/descriptor.hpp"
40 #include "vm/exceptions.hpp"
41 #include "vm/global.hpp"
42 #include "vm/globals.hpp"
43 #include "vm/initialize.hpp"
44 #include "vm/javaobjects.hpp"
45 #include "vm/method.hpp"
46 #include "vm/vm.hpp"
47 
48 #include "vm/jit/builtin.hpp"
49 
50 
51 /**
52  * Invoke a method on the given object with the given arguments.
53  *
54  * For instance methods OBJ must be != NULL and the method is looked up
55  * in the vftbl of the object.
56  *
57  * For static methods, OBJ is ignored.
58  */
60 {
61  methodinfo *resm;
62  java_handle_t *ro;
63  int argcount;
64  int paramcount;
65 
66  /* Sanity check. */
67 
68  assert(m != NULL);
69 
70  argcount = m->parseddesc->paramcount;
71  paramcount = argcount;
72 
73  /* If method is non-static, remove the `this' pointer. */
74 
75  if (!(m->flags & ACC_STATIC))
76  paramcount--;
77 
78  /* For instance methods the object has to be an instance of the
79  class the method belongs to. For static methods the obj
80  parameter is ignored. */
81 
82  if (!(m->flags & ACC_STATIC) && o && (!builtin_instanceof(o, m->clazz))) {
84  return NULL;
85  }
86 
87  /* check if we got the right number of arguments */
88 
89  ObjectArray oa(params);
90 
91  if (((params == NULL) && (paramcount != 0)) ||
92  (params && (oa.get_length() != paramcount)))
93  {
95  return NULL;
96  }
97 
98  /* for instance methods we need an object */
99 
100  if (!(m->flags & ACC_STATIC) && (o == NULL)) {
101  /* XXX not sure if that is the correct exception */
103  return NULL;
104  }
105 
106  /* for static methods, zero object to make subsequent code simpler */
107  if (m->flags & ACC_STATIC)
108  o = NULL;
109 
110  if (o != NULL) {
111  /* for instance methods we must do a vftbl lookup */
113  }
114  else {
115  /* for static methods, just for convenience */
116  resm = m;
117  }
118 
119  ro = vm_call_method_objectarray(resm, o, params);
120 
121  return ro;
122 }
123 
124 
125 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH) && defined(ENABLE_ANNOTATIONS)
126 /* reflect_get_declaredannotations *********************************************
127 
128  Calls the annotation parser with the unparsed annotations and returnes
129  the parsed annotations as a map.
130 
131  IN:
132  annotations........the unparsed annotations
133  declaringClass.....the class in which the annotated element is declared
134  referer............the calling class (for the 'referer' parameter of
135  vm_call_method())
136 
137  RETURN VALUE:
138  The parsed annotations as a
139  java.util.Map<Class<? extends Annotation>, Annotation>.
140 
141 *******************************************************************************/
142 
144 {
145  static methodinfo* m_parseAnnotations = NULL;
146 
148 
149  if (h == NULL)
150  return NULL;
151 
153  cp.set_constantPoolOop(declaringClass);
154 
155  /* only resolve the parser method the first time */
156  if (m_parseAnnotations == NULL) {
157  // FIXME Use globals.
158  Utf8String utf_parseAnnotations = Utf8String::from_utf8("parseAnnotations");
159  Utf8String utf_desc = Utf8String::from_utf8("([BLsun/reflect/ConstantPool;Ljava/lang/Class;)Ljava/util/Map;");
160 
161  if (utf_parseAnnotations == NULL || utf_desc == NULL)
162  return NULL;
163 
164  m_parseAnnotations = class_resolveclassmethod(
166  utf_parseAnnotations,
167  utf_desc,
168  referer,
169  true);
170 
171  if (m_parseAnnotations == NULL)
172  return NULL;
173  }
174 
175  return (java_handle_t*) vm_call_method(m_parseAnnotations, NULL, annotations, cp.get_handle(), declaringClass);
176 }
177 
178 
179 /* reflect_get_parameterannotations *******************************************
180 
181  Calls the annotation parser with the unparsed parameter annotations of
182  a method and returnes the parsed parameter annotations in a 2 dimensional
183  array.
184 
185  IN:
186  parameterAnnotations....the unparsed parameter annotations
187  slot....................the slot of the method
188  declaringClass..........the class in which the annotated element is
189  declared
190  referer.................the calling class (for the 'referer' parameter
191  of vm_call_method())
192 
193  RETURN VALUE:
194  The parsed parameter annotations in a 2 dimensional array.
195 
196 *******************************************************************************/
197 
199 {
200  /* This method in java would be basically the following.
201  * We don't do it in java because we don't want to make a
202  * public method with wich you can get a ConstantPool, because
203  * with that you could read any kind of constants (even private
204  * ones).
205  *
206  * ConstantPool constPool = new ConstantPool();
207  * constPool.constantPoolOop = method.getDeclaringClass();
208  * return sun.reflect.AnnotationParser.parseParameterAnnotations(
209  * parameterAnnotations,
210  * constPool,
211  * method.getDeclaringClass(),
212  * method.getParameterTypes().length);
213  */
214 
215  static methodinfo* m_parseParameterAnnotations = NULL;
216 
217  /* get parameter count */
218 
219  int32_t numParameters = method_get_parametercount(m);
220 
221  /* get ConstantPool */
222 
224 
225  if (h == NULL)
226  return NULL;
227 
229  cp.set_constantPoolOop(m->clazz);
230 
231  /* only resolve the parser method the first time */
232  if (m_parseParameterAnnotations == NULL) {
233  Utf8String utf_parseParameterAnnotations = Utf8String::from_utf8("parseParameterAnnotations");
234  Utf8String utf_desc = Utf8String::from_utf8("([BLsun/reflect/ConstantPool;Ljava/lang/Class;I)[[Ljava/lang/annotation/Annotation;");
235 
236  if (utf_parseParameterAnnotations == NULL || utf_desc == NULL)
237  return NULL;
238 
239  /* get parser method */
240 
241  m_parseParameterAnnotations = class_resolveclassmethod(
243  utf_parseParameterAnnotations,
244  utf_desc,
245  referer,
246  true);
247 
248  if (m_parseParameterAnnotations == NULL)
249  return NULL;
250  }
251 
252  return (java_handle_objectarray_t*) vm_call_method(m_parseParameterAnnotations, NULL, parameterAnnotations, cp.get_handle(), m->clazz, numParameters);
253 }
254 #endif
255 
256 
257 /*
258  * These are local overrides for various environment variables in Emacs.
259  * Please do not remove this and leave it at the end of the file, where
260  * Emacs will automagically detect them.
261  * ---------------------------------------------------------------------
262  * Local variables:
263  * mode: c++
264  * indent-tabs-mode: t
265  * c-basic-offset: 4
266  * tab-width: 4
267  * End:
268  * vim:noexpandtab:sw=4:ts=4:
269  */
void exceptions_throw_illegalargumentexception(void)
static java_handle_t * get_declaredannotations(java_handle_bytearray_t *annotations, classinfo *declaringClass, classinfo *referer)
Definition: reflection.cpp:143
bool builtin_instanceof(java_handle_t *o, classinfo *c)
Definition: builtin.cpp:403
methodinfo * class_resolveclassmethod(classinfo *c, Utf8String name, Utf8String desc, classinfo *referer, bool throwexception)
Definition: class.cpp:1211
virtual java_handle_t * get_handle() const
void set_constantPoolOop(classinfo *value)
classinfo * class_sun_reflect_annotation_AnnotationParser
Definition: globals.cpp:99
OpenJDK sun/reflect/ConstantPool.
Actual implementation of access class for Java Object arrays.
Definition: array.hpp:381
methodinfo * method_vftbl_lookup(vftbl_t *vftbl, methodinfo *m)
Definition: method.cpp:697
static java_handle_objectarray_t * get_parameterannotations(java_handle_bytearray_t *parameterAnnotations, methodinfo *m, classinfo *referer)
Definition: reflection.cpp:198
static java_handle_t * invoke(methodinfo *m, java_handle_t *o, java_handle_objectarray_t *params)
Invoke a method on the given object with the given arguments.
Definition: reflection.cpp:59
java_handle_t * vm_call_method(methodinfo *m, java_handle_t *o,...)
int32_t method_get_parametercount(methodinfo *m)
Definition: method.cpp:742
classinfo * class_sun_reflect_ConstantPool
Definition: globals.cpp:97
int32_t get_length() const
Definition: array.hpp:189
classinfo * clazz
Definition: method.hpp:80
void exceptions_throw_nullpointerexception(void)
static Utf8String from_utf8(const char *, size_t)
Definition: utf8.cpp:335
java_handle_t * native_new_and_init(classinfo *c)
Registers a new native agent by specified by it&#39;s library name and with an optional options string...
Definition: native.cpp:729
java_handle_t * vm_call_method_objectarray(methodinfo *m, java_handle_t *o, java_handle_objectarray_t *params)
Definition: vm.cpp:2483
#define LLNI_vftbl_direct(obj)
Definition: llni.hpp:120
methoddesc * parseddesc
Definition: method.hpp:78
s4 flags
Definition: method.hpp:70