Line data Source code
1 : /* src/vm/javaobjects.cpp - functions to create and access Java objects
2 :
3 : Copyright (C) 1996-2013
4 : CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5 : Copyright (C) 2008, 2009 Theobroma Systems Ltd.
6 :
7 : This file is part of CACAO.
8 :
9 : This program is free software; you can redistribute it and/or
10 : modify it under the terms of the GNU General Public License as
11 : published by the Free Software Foundation; either version 2, or (at
12 : your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful, but
15 : WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 : General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program; if not, write to the Free Software
21 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 : 02110-1301, USA.
23 :
24 : */
25 :
26 :
27 : #include "config.h"
28 :
29 : #include <stdint.h>
30 :
31 : #include "native/vm/reflection.hpp"
32 :
33 : #include "vm/access.hpp"
34 : #include "vm/jit/builtin.hpp"
35 : #include "vm/global.hpp"
36 : #include "vm/globals.hpp"
37 : #include "vm/initialize.hpp"
38 : #include "vm/javaobjects.hpp"
39 : #include "vm/vm.hpp"
40 :
41 : #include <map>
42 :
43 : #if defined(ENABLE_JAVASE)
44 :
45 : /**
46 : * Invokes the static Java method getSystemClassLoader().
47 : *
48 : * @return Return value of the invocation or NULL in
49 : * case of an exception.
50 : */
51 141 : java_handle_t* java_lang_ClassLoader::invoke_getSystemClassLoader()
52 : {
53 : methodinfo *m;
54 : java_handle_t *clo;
55 : classloader_t *cl;
56 :
57 141 : assert(class_java_lang_Object);
58 141 : assert(class_java_lang_ClassLoader);
59 141 : assert(class_java_lang_ClassLoader->state & CLASS_LINKED);
60 :
61 : m = class_resolveclassmethod(class_java_lang_ClassLoader,
62 : utf8::getSystemClassLoader,
63 : utf8::void__java_lang_ClassLoader,
64 : class_java_lang_Object,
65 141 : false);
66 :
67 141 : if (m == NULL)
68 0 : return NULL;
69 :
70 141 : clo = vm_call_method(m, NULL);
71 :
72 141 : if (clo == NULL)
73 0 : return NULL;
74 :
75 141 : cl = loader_hashtable_classloader_add(clo);
76 :
77 141 : return cl;
78 : }
79 :
80 :
81 : /**
82 : * Constructs a new instance of the class by calling the
83 : * appropriate Java initializer.
84 : */
85 0 : java_lang_management_MemoryUsage::java_lang_management_MemoryUsage(int64_t init, int64_t used, int64_t commited, int64_t maximum)
86 : {
87 : // Load the class.
88 : // XXX Maybe this should be made global at some points.
89 : classinfo* class_java_lang_management_MemoryUsage;
90 0 : if (!(class_java_lang_management_MemoryUsage = load_class_bootstrap(Utf8String::from_utf8("java/lang/management/MemoryUsage"))))
91 0 : return;
92 :
93 : // Find the appropriate initializer.
94 : // XXX Maybe this should be made global at some points.
95 : methodinfo* m = class_findmethod(class_java_lang_management_MemoryUsage,
96 : utf8::init,
97 0 : Utf8String::from_utf8("(JJJJ)V"));
98 :
99 0 : if (m == NULL)
100 0 : return;
101 :
102 : // Instantiate a new object.
103 0 : _handle = builtin_new(class_java_lang_management_MemoryUsage);
104 :
105 0 : if (is_null())
106 0 : return;
107 :
108 : // Call initializer.
109 0 : (void) vm_call_method(m, _handle, init, used, commited, maximum);
110 0 : }
111 :
112 :
113 : /**
114 : * Constructs a Java object with the given
115 : * java.lang.reflect.Constructor.
116 : *
117 : * @param args Constructor arguments.
118 : *
119 : * @return Handle to Java object.
120 : */
121 468 : java_handle_t* java_lang_reflect_Constructor::new_instance(java_handle_objectarray_t* args)
122 : {
123 468 : methodinfo* m = get_method();
124 :
125 : // Should we bypass security the checks (AccessibleObject)?
126 468 : if (get_override() == false) {
127 : /* This method is always called like this:
128 : [0] java.lang.reflect.Constructor.constructNative (Native Method)
129 : [1] java.lang.reflect.Constructor.newInstance
130 : [2] <caller>
131 : */
132 :
133 468 : if (!access_check_method(m, 2))
134 0 : return NULL;
135 : }
136 :
137 : // Create a Java object.
138 468 : java_handle_t* h = builtin_new(m->clazz);
139 :
140 468 : if (h == NULL)
141 0 : return NULL;
142 :
143 : // Call initializer.
144 468 : (void) Reflection::invoke(m, h, args);
145 :
146 468 : return h;
147 : }
148 :
149 :
150 : /**
151 : * Invokes the given method.
152 : *
153 : * @param args Method arguments.
154 : *
155 : * @return return value of the method
156 : */
157 385 : java_handle_t* java_lang_reflect_Method::invoke(java_handle_t* o, java_handle_objectarray_t* args)
158 : {
159 385 : methodinfo* m = get_method();
160 :
161 : // Should we bypass security the checks (AccessibleObject)?
162 385 : if (get_override() == false) {
163 : #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
164 : /* This method is always called like this:
165 : [0] java.lang.reflect.Method.invokeNative (Native Method)
166 : [1] java.lang.reflect.Method.invoke (Method.java:329)
167 : [2] <caller>
168 : */
169 :
170 363 : if (!access_check_method(m, 2))
171 0 : return NULL;
172 : #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
173 : /* We only pass 0 here as stacktrace_get_caller_class, which
174 : is called from access_check_method, skips
175 : java.lang.reflect.Method.invoke(). */
176 :
177 : if (!access_check_method(m, 0))
178 : return NULL;
179 : #else
180 : # error unknown classpath configuration
181 : #endif
182 : }
183 :
184 : // Check if method class is initialized.
185 385 : if (!(m->clazz->state & CLASS_INITIALIZED))
186 9 : if (!initialize_class(m->clazz))
187 0 : return NULL;
188 :
189 : // Call the Java method.
190 385 : java_handle_t* result = Reflection::invoke(m, o, args);
191 :
192 385 : return result;
193 : }
194 :
195 : struct DynOffsetEntry {
196 : void (*setter)(int32_t);
197 : const char *name;
198 : };
199 :
200 : typedef std::map<classinfo *, DynOffsetEntry *> RegisteredDynMap;
201 165 : static RegisteredDynMap dynEntryMap;
202 :
203 163 : static void register_dyn_entry_table(classinfo *c, DynOffsetEntry *entries)
204 : {
205 163 : dynEntryMap.insert(std::make_pair(c, entries));
206 163 : }
207 :
208 978 : static bool runAllSetters(classinfo *c, DynOffsetEntry entries[])
209 : {
210 978 : do {
211 978 : fieldinfo *fi = class_findfield_by_name(c, Utf8String::from_utf8(entries->name));
212 978 : if (!fi)
213 0 : return false;
214 978 : entries->setter(fi->offset);
215 : } while ((++entries)->setter);
216 163 : return true;
217 : }
218 :
219 42202 : bool jobjects_run_dynoffsets_hook(classinfo *c)
220 : {
221 42202 : RegisteredDynMap::const_iterator it = dynEntryMap.find(c);
222 42202 : if (it == dynEntryMap.end())
223 42039 : return true;
224 :
225 163 : if (!runAllSetters(c, it->second))
226 0 : return false;
227 :
228 163 : return true;
229 : }
230 :
231 : #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
232 :
233 : off_t java_lang_Thread::offset_vmThread;
234 : off_t java_lang_Thread::offset_group;
235 : off_t java_lang_Thread::offset_name;
236 : off_t java_lang_Thread::offset_daemon;
237 : off_t java_lang_Thread::offset_priority;
238 : off_t java_lang_Thread::offset_exceptionHandler;
239 :
240 : static DynOffsetEntry dyn_entries_java_lang_Thread[] = {
241 : { &java_lang_Thread::set_vmThread_offset, "vmThread" },
242 : { &java_lang_Thread::set_group_offset, "group" },
243 : { &java_lang_Thread::set_name_offset, "name" },
244 : { &java_lang_Thread::set_daemon_offset, "daemon" },
245 : { &java_lang_Thread::set_priority_offset, "priority" },
246 : { &java_lang_Thread::set_exceptionHandler_offset, "exceptionHandler" },
247 : { 0, 0 }
248 : };
249 :
250 : #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
251 :
252 : off_t java_lang_Thread::offset_priority;
253 : off_t java_lang_Thread::offset_daemon;
254 : off_t java_lang_Thread::offset_group;
255 : off_t java_lang_Thread::offset_uncaughtExceptionHandler;
256 : off_t java_lang_Thread::offset_threadStatus;
257 : #ifndef WITH_JAVA_RUNTIME_LIBRARY_OPENJDK_7
258 : off_t java_lang_Thread::offset_me;
259 : #endif
260 :
261 : static DynOffsetEntry dyn_entries_java_lang_Thread[] = {
262 : { &java_lang_Thread::set_priority_offset, "priority" },
263 : { &java_lang_Thread::set_daemon_offset, "daemon" },
264 : { &java_lang_Thread::set_group_offset, "group" },
265 : { &java_lang_Thread::set_uncaughtExceptionHandler_offset, "uncaughtExceptionHandler" },
266 : { &java_lang_Thread::set_threadStatus_offset, "threadStatus" },
267 : #ifndef WITH_JAVA_RUNTIME_LIBRARY_OPENJDK_7
268 : { &java_lang_Thread::set_me_offset, "me" },
269 : #endif
270 : { 0, 0 }
271 : };
272 :
273 : #endif
274 :
275 163 : void jobjects_register_dyn_offsets()
276 : {
277 163 : register_dyn_entry_table(class_java_lang_Thread, dyn_entries_java_lang_Thread);
278 658 : }
279 :
280 : #endif // ENABLE_JAVASE
281 :
282 :
283 : /*
284 : * These are local overrides for various environment variables in Emacs.
285 : * Please do not remove this and leave it at the end of the file, where
286 : * Emacs will automagically detect them.
287 : * ---------------------------------------------------------------------
288 : * Local variables:
289 : * mode: c++
290 : * indent-tabs-mode: t
291 : * c-basic-offset: 4
292 : * tab-width: 4
293 : * End:
294 : * vim:noexpandtab:sw=4:ts=4:
295 : */
|