* src/threads/thread.cpp: Break a reference cycle.
[cacao.git] / src / vm / javaobjects.cpp
1 /* src/vm/javaobjects.cpp - functions to create and access Java objects
2
3    Copyright (C) 1996-2011
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.h"
36 #include "vm/globals.hpp"
37 #include "vm/initialize.hpp"
38 #include "vm/javaobjects.hpp"
39
40 #include <map>
41
42 #if defined(ENABLE_JAVASE)
43
44 /**
45  * Invokes the static Java method getSystemClassLoader().
46  *
47  * @return Return value of the invocation or NULL in
48  * case of an exception.
49  */
50 java_handle_t* java_lang_ClassLoader::invoke_getSystemClassLoader()
51 {
52         methodinfo    *m;
53         java_handle_t *clo;
54         classloader_t *cl;
55
56         assert(class_java_lang_Object);
57         assert(class_java_lang_ClassLoader);
58         assert(class_java_lang_ClassLoader->state & CLASS_LINKED);
59
60         m = class_resolveclassmethod(class_java_lang_ClassLoader,
61                                                                  utf_getSystemClassLoader,
62                                                                  utf_void__java_lang_ClassLoader,
63                                                                  class_java_lang_Object,
64                                                                  false);
65
66         if (m == NULL)
67                 return NULL;
68
69         clo = vm_call_method(m, NULL);
70
71         if (clo == NULL)
72                 return NULL;
73
74         cl = loader_hashtable_classloader_add(clo);
75
76         return cl;
77 }
78
79
80 /**
81  * Constructs a new instance of the class by calling the
82  * appropriate Java initializer.
83  */
84 java_lang_management_MemoryUsage::java_lang_management_MemoryUsage(int64_t init, int64_t used, int64_t commited, int64_t maximum)
85 {
86         // Load the class.
87         // XXX Maybe this should be made global at some points.
88         classinfo* class_java_lang_management_MemoryUsage;
89         if (!(class_java_lang_management_MemoryUsage = load_class_bootstrap(utf_new_char("java/lang/management/MemoryUsage"))))
90                 return;
91
92         // Find the appropriate initializer.
93         // XXX Maybe this should be made global at some points.
94         methodinfo* m = class_findmethod(class_java_lang_management_MemoryUsage,
95                                                                          utf_init,
96                                                                          utf_new_char("(JJJJ)V"));
97
98         if (m == NULL)
99                 return;
100
101         // Instantiate a new object.
102         _handle = builtin_new(class_java_lang_management_MemoryUsage);
103
104         if (is_null())
105                 return;
106
107         // Call initializer.
108         (void) vm_call_method(m, _handle, init, used, commited, maximum);
109 }
110
111
112 /**
113  * Constructs a Java object with the given
114  * java.lang.reflect.Constructor.
115  *
116  * @param args     Constructor arguments.
117  *
118  * @return Handle to Java object.
119  */
120 java_handle_t* java_lang_reflect_Constructor::new_instance(java_handle_objectarray_t* args)
121 {
122         methodinfo* m = get_method();
123
124         // Should we bypass security the checks (AccessibleObject)?
125         if (get_override() == false) {
126                 /* This method is always called like this:
127                        [0] java.lang.reflect.Constructor.constructNative (Native Method)
128                        [1] java.lang.reflect.Constructor.newInstance
129                        [2] <caller>
130                 */
131
132                 if (!access_check_method(m, 2))
133                         return NULL;
134         }
135
136         // Create a Java object.
137         java_handle_t* h = builtin_new(m->clazz);
138
139         if (h == NULL)
140                 return NULL;
141
142         // Call initializer.
143         (void) Reflection::invoke(m, h, args);
144
145         return h;
146 }
147
148
149 /**
150  * Invokes the given method.
151  *
152  * @param args Method arguments.
153  *
154  * @return return value of the method
155  */
156 java_handle_t* java_lang_reflect_Method::invoke(java_handle_t* o, java_handle_objectarray_t* args)
157 {
158         methodinfo* m = get_method();
159
160         // Should we bypass security the checks (AccessibleObject)?
161         if (get_override() == false) {
162 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
163                 /* This method is always called like this:
164                        [0] java.lang.reflect.Method.invokeNative (Native Method)
165                        [1] java.lang.reflect.Method.invoke (Method.java:329)
166                        [2] <caller>
167                 */
168
169                 if (!access_check_method(m, 2))
170                         return NULL;
171 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
172                 /* We only pass 1 here as stacktrace_get_caller_class, which
173                    is called from access_check_method, skips
174                    java.lang.reflect.Method.invoke(). */
175
176                 if (!access_check_method(m, 1))
177                         return NULL;
178 #else
179 # error unknown classpath configuration
180 #endif
181         }
182
183         // Check if method class is initialized.
184         if (!(m->clazz->state & CLASS_INITIALIZED))
185                 if (!initialize_class(m->clazz))
186                         return NULL;
187
188         // Call the Java method.
189         java_handle_t* result = Reflection::invoke(m, o, args);
190
191         return result;
192 }
193
194 struct DynOffsetEntry {
195         void (*setter)(int32_t);
196         const char *name;
197 };
198
199 typedef std::map<classinfo *, DynOffsetEntry *> RegisteredDynMap;
200 static RegisteredDynMap dynEntryMap;
201
202 static void register_dyn_entry_table(classinfo *c, DynOffsetEntry *entries)
203 {
204         dynEntryMap.insert(std::make_pair(c, entries));
205 }
206
207 static bool runAllSetters(classinfo *c, DynOffsetEntry entries[])
208 {
209         do {
210                 fieldinfo *fi = class_findfield_by_name(c, utf_new_char(entries->name));
211                 if (!fi)
212                         return false;
213                 entries->setter(fi->offset);
214         } while ((++entries)->setter);
215         return true;
216 }
217
218 bool jobjects_run_dynoffsets_hook(classinfo *c)
219 {
220         RegisteredDynMap::const_iterator it = dynEntryMap.find(c);
221         if (it == dynEntryMap.end())
222                 return true;
223
224         if (!runAllSetters(c, it->second))
225                 return false;
226
227         return true;
228 }
229
230 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
231
232 off_t java_lang_Thread::offset_vmThread;
233 off_t java_lang_Thread::offset_group;
234 off_t java_lang_Thread::offset_name;
235 off_t java_lang_Thread::offset_daemon;
236 off_t java_lang_Thread::offset_priority;
237 off_t java_lang_Thread::offset_exceptionHandler;
238
239 static DynOffsetEntry dyn_entries_java_lang_Thread[] = {
240         { &java_lang_Thread::set_vmThread_offset,         "vmThread" },
241         { &java_lang_Thread::set_group_offset,            "group" },
242         { &java_lang_Thread::set_name_offset,             "name" },
243         { &java_lang_Thread::set_daemon_offset,           "daemon" },
244         { &java_lang_Thread::set_priority_offset,         "priority" },
245         { &java_lang_Thread::set_exceptionHandler_offset, "exceptionHandler" },
246         { 0, 0 }
247 };
248
249 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
250
251 off_t java_lang_Thread::offset_priority;
252 off_t java_lang_Thread::offset_daemon;
253 off_t java_lang_Thread::offset_group;
254 off_t java_lang_Thread::offset_uncaughtExceptionHandler;
255 off_t java_lang_Thread::offset_threadStatus;
256 off_t java_lang_Thread::offset_me;
257
258 static DynOffsetEntry dyn_entries_java_lang_Thread[] = {
259         { &java_lang_Thread::set_priority_offset,                 "priority" },
260         { &java_lang_Thread::set_daemon_offset,                   "daemon" },
261         { &java_lang_Thread::set_group_offset,                    "group" },
262         { &java_lang_Thread::set_uncaughtExceptionHandler_offset, "uncaughtExceptionHandler" },
263         { &java_lang_Thread::set_threadStatus_offset,             "threadStatus" },
264         { &java_lang_Thread::set_me_offset,                       "me" },
265         { 0, 0 }
266 };
267
268 #endif
269
270 void jobjects_register_dyn_offsets()
271 {
272         register_dyn_entry_table(class_java_lang_Thread, dyn_entries_java_lang_Thread);
273 }
274
275 #endif // ENABLE_JAVASE
276
277
278 /*
279  * These are local overrides for various environment variables in Emacs.
280  * Please do not remove this and leave it at the end of the file, where
281  * Emacs will automagically detect them.
282  * ---------------------------------------------------------------------
283  * Local variables:
284  * mode: c++
285  * indent-tabs-mode: t
286  * c-basic-offset: 4
287  * tab-width: 4
288  * End:
289  * vim:noexpandtab:sw=4:ts=4:
290  */