Mercurial > hg > truffle
annotate src/share/vm/prims/jvmtiGetLoadedClasses.cpp @ 12233:40136aa2cdb1
8010722: assert: failed: heap size is too big for compressed oops
Summary: Use conservative assumptions of required alignment for the various garbage collector components into account when determining the maximum heap size that supports compressed oops. Using this conservative value avoids several circular dependencies in the calculation.
Reviewed-by: stefank, dholmes
author | tschatzl |
---|---|
date | Wed, 11 Sep 2013 16:25:02 +0200 |
parents | 070d523b96a7 |
children | e64f1fe9756b |
rev | line source |
---|---|
0 | 1 /* |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
2 * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "classfile/systemDictionary.hpp" | |
27 #include "memory/universe.inline.hpp" | |
28 #include "prims/jvmtiGetLoadedClasses.hpp" | |
29 #include "runtime/thread.hpp" | |
0 | 30 |
31 | |
32 | |
33 // The closure for GetLoadedClasses and GetClassLoaderClasses | |
34 class JvmtiGetLoadedClassesClosure : public StackObj { | |
35 // Since the SystemDictionary::classes_do callback | |
36 // doesn't pass a closureData pointer, | |
37 // we use a thread-local slot to hold a pointer to | |
38 // a stack allocated instance of this structure. | |
39 private: | |
40 jobject _initiatingLoader; | |
41 int _count; | |
42 Handle* _list; | |
43 int _index; | |
44 | |
45 private: | |
46 // Getting and setting the thread local pointer | |
47 static JvmtiGetLoadedClassesClosure* get_this() { | |
48 JvmtiGetLoadedClassesClosure* result = NULL; | |
49 JavaThread* thread = JavaThread::current(); | |
50 result = thread->get_jvmti_get_loaded_classes_closure(); | |
51 return result; | |
52 } | |
53 static void set_this(JvmtiGetLoadedClassesClosure* that) { | |
54 JavaThread* thread = JavaThread::current(); | |
55 thread->set_jvmti_get_loaded_classes_closure(that); | |
56 } | |
57 | |
58 public: | |
59 // Constructor/Destructor | |
60 JvmtiGetLoadedClassesClosure() { | |
61 JvmtiGetLoadedClassesClosure* that = get_this(); | |
62 assert(that == NULL, "JvmtiGetLoadedClassesClosure in use"); | |
63 _initiatingLoader = NULL; | |
64 _count = 0; | |
65 _list = NULL; | |
66 _index = 0; | |
67 set_this(this); | |
68 } | |
69 | |
70 JvmtiGetLoadedClassesClosure(jobject initiatingLoader) { | |
71 JvmtiGetLoadedClassesClosure* that = get_this(); | |
72 assert(that == NULL, "JvmtiGetLoadedClassesClosure in use"); | |
73 _initiatingLoader = initiatingLoader; | |
74 _count = 0; | |
75 _list = NULL; | |
76 _index = 0; | |
77 set_this(this); | |
78 } | |
79 | |
80 ~JvmtiGetLoadedClassesClosure() { | |
81 JvmtiGetLoadedClassesClosure* that = get_this(); | |
82 assert(that != NULL, "JvmtiGetLoadedClassesClosure not found"); | |
83 set_this(NULL); | |
84 _initiatingLoader = NULL; | |
85 _count = 0; | |
86 if (_list != NULL) { | |
87 FreeHeap(_list); | |
88 _list = NULL; | |
89 } | |
90 _index = 0; | |
91 } | |
92 | |
93 // Accessors. | |
94 jobject get_initiatingLoader() { | |
95 return _initiatingLoader; | |
96 } | |
97 | |
98 int get_count() { | |
99 return _count; | |
100 } | |
101 | |
102 void set_count(int value) { | |
103 _count = value; | |
104 } | |
105 | |
106 Handle* get_list() { | |
107 return _list; | |
108 } | |
109 | |
110 void set_list(Handle* value) { | |
111 _list = value; | |
112 } | |
113 | |
114 int get_index() { | |
115 return _index; | |
116 } | |
117 | |
118 void set_index(int value) { | |
119 _index = value; | |
120 } | |
121 | |
122 Handle get_element(int index) { | |
123 if ((_list != NULL) && (index < _count)) { | |
124 return _list[index]; | |
125 } else { | |
126 assert(false, "empty get_element"); | |
127 return Handle(); | |
128 } | |
129 } | |
130 | |
131 void set_element(int index, Handle value) { | |
132 if ((_list != NULL) && (index < _count)) { | |
133 _list[index] = value; | |
134 } else { | |
135 assert(false, "bad set_element"); | |
136 } | |
137 } | |
138 | |
139 // Other predicates | |
140 bool available() { | |
141 return (_list != NULL); | |
142 } | |
143 | |
144 #ifdef ASSERT | |
145 // For debugging. | |
146 void check(int limit) { | |
147 for (int i = 0; i < limit; i += 1) { | |
148 assert(Universe::heap()->is_in(get_element(i)()), "check fails"); | |
149 } | |
150 } | |
151 #endif | |
152 | |
153 // Public methods that get called within the scope of the closure | |
154 void allocate() { | |
6197 | 155 _list = NEW_C_HEAP_ARRAY(Handle, _count, mtInternal); |
0 | 156 assert(_list != NULL, "Out of memory"); |
157 if (_list == NULL) { | |
158 _count = 0; | |
159 } | |
160 } | |
161 | |
162 void extract(JvmtiEnv *env, jclass* result) { | |
163 for (int index = 0; index < _count; index += 1) { | |
164 result[index] = (jclass) env->jni_reference(get_element(index)); | |
165 } | |
166 } | |
167 | |
168 // Finally, the static methods that are the callbacks | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
169 static void increment(Klass* k) { |
0 | 170 JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this(); |
171 if (that->get_initiatingLoader() == NULL) { | |
6983 | 172 for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) { |
0 | 173 that->set_count(that->get_count() + 1); |
174 } | |
175 } else if (k != NULL) { | |
176 // if initiating loader not null, just include the instance with 1 dimension | |
177 that->set_count(that->get_count() + 1); | |
178 } | |
179 } | |
180 | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
181 static void increment_with_loader(Klass* k, ClassLoaderData* loader_data) { |
0 | 182 JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this(); |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
183 oop class_loader = loader_data->class_loader(); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
184 if (class_loader == JNIHandles::resolve(that->get_initiatingLoader())) { |
6983 | 185 for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) { |
0 | 186 that->set_count(that->get_count() + 1); |
187 } | |
188 } | |
189 } | |
190 | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
191 static void prim_array_increment_with_loader(Klass* array, ClassLoaderData* loader_data) { |
0 | 192 JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this(); |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
193 oop class_loader = loader_data->class_loader(); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
194 if (class_loader == JNIHandles::resolve(that->get_initiatingLoader())) { |
0 | 195 that->set_count(that->get_count() + 1); |
196 } | |
197 } | |
198 | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
199 static void add(Klass* k) { |
0 | 200 JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this(); |
201 if (that->available()) { | |
202 if (that->get_initiatingLoader() == NULL) { | |
6983 | 203 for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) { |
204 oop mirror = l->java_mirror(); | |
0 | 205 that->set_element(that->get_index(), mirror); |
206 that->set_index(that->get_index() + 1); | |
207 } | |
208 } else if (k != NULL) { | |
209 // if initiating loader not null, just include the instance with 1 dimension | |
6983 | 210 oop mirror = k->java_mirror(); |
0 | 211 that->set_element(that->get_index(), mirror); |
212 that->set_index(that->get_index() + 1); | |
213 } | |
214 } | |
215 } | |
216 | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
217 static void add_with_loader(Klass* k, ClassLoaderData* loader_data) { |
0 | 218 JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this(); |
219 if (that->available()) { | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
220 oop class_loader = loader_data->class_loader(); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
221 if (class_loader == JNIHandles::resolve(that->get_initiatingLoader())) { |
6983 | 222 for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) { |
223 oop mirror = l->java_mirror(); | |
0 | 224 that->set_element(that->get_index(), mirror); |
225 that->set_index(that->get_index() + 1); | |
226 } | |
227 } | |
228 } | |
229 } | |
230 | |
231 // increment the count for the given basic type array class (and any | |
232 // multi-dimensional arrays). For example, for [B we check for | |
233 // [[B, [[[B, .. and the count is incremented for each one that exists. | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
234 static void increment_for_basic_type_arrays(Klass* k) { |
0 | 235 JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this(); |
236 assert(that != NULL, "no JvmtiGetLoadedClassesClosure"); | |
6983 | 237 for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) { |
0 | 238 that->set_count(that->get_count() + 1); |
239 } | |
240 } | |
241 | |
242 // add the basic type array class and its multi-dimensional array classes to the list | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
243 static void add_for_basic_type_arrays(Klass* k) { |
0 | 244 JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this(); |
245 assert(that != NULL, "no JvmtiGetLoadedClassesClosure"); | |
246 assert(that->available(), "no list"); | |
6983 | 247 for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) { |
248 oop mirror = l->java_mirror(); | |
0 | 249 that->set_element(that->get_index(), mirror); |
250 that->set_index(that->get_index() + 1); | |
251 } | |
252 } | |
253 }; | |
254 | |
255 | |
256 jvmtiError | |
257 JvmtiGetLoadedClasses::getLoadedClasses(JvmtiEnv *env, jint* classCountPtr, jclass** classesPtr) { | |
258 // Since SystemDictionary::classes_do only takes a function pointer | |
259 // and doesn't call back with a closure data pointer, | |
260 // we can only pass static methods. | |
261 | |
262 JvmtiGetLoadedClassesClosure closure; | |
263 { | |
264 // To get a consistent list of classes we need MultiArray_lock to ensure | |
265 // array classes aren't created, and SystemDictionary_lock to ensure that | |
266 // classes aren't added to the system dictionary, | |
267 MutexLocker ma(MultiArray_lock); | |
268 MutexLocker sd(SystemDictionary_lock); | |
269 | |
270 // First, count the classes | |
271 SystemDictionary::classes_do(&JvmtiGetLoadedClassesClosure::increment); | |
272 Universe::basic_type_classes_do(&JvmtiGetLoadedClassesClosure::increment); | |
273 // Next, fill in the classes | |
274 closure.allocate(); | |
275 SystemDictionary::classes_do(&JvmtiGetLoadedClassesClosure::add); | |
276 Universe::basic_type_classes_do(&JvmtiGetLoadedClassesClosure::add); | |
277 // Drop the SystemDictionary_lock, so the results could be wrong from here, | |
278 // but we still have a snapshot. | |
279 } | |
280 // Post results | |
281 jclass* result_list; | |
282 jvmtiError err = env->Allocate(closure.get_count() * sizeof(jclass), | |
283 (unsigned char**)&result_list); | |
284 if (err != JVMTI_ERROR_NONE) { | |
285 return err; | |
286 } | |
287 closure.extract(env, result_list); | |
288 *classCountPtr = closure.get_count(); | |
289 *classesPtr = result_list; | |
290 return JVMTI_ERROR_NONE; | |
291 } | |
292 | |
293 jvmtiError | |
294 JvmtiGetLoadedClasses::getClassLoaderClasses(JvmtiEnv *env, jobject initiatingLoader, | |
295 jint* classCountPtr, jclass** classesPtr) { | |
296 // Since SystemDictionary::classes_do only takes a function pointer | |
297 // and doesn't call back with a closure data pointer, | |
298 // we can only pass static methods. | |
299 JvmtiGetLoadedClassesClosure closure(initiatingLoader); | |
300 { | |
301 // To get a consistent list of classes we need MultiArray_lock to ensure | |
302 // array classes aren't created, and SystemDictionary_lock to ensure that | |
303 // classes aren't added to the system dictionary, | |
304 MutexLocker ma(MultiArray_lock); | |
305 MutexLocker sd(SystemDictionary_lock); | |
306 // First, count the classes in the system dictionary which have this loader recorded | |
307 // as an initiating loader. For basic type arrays this information is not recorded | |
308 // so GetClassLoaderClasses will return all of the basic type arrays. This is okay | |
309 // because the defining loader for basic type arrays is always the boot class loader | |
310 // and these classes are "visible" to all loaders. | |
311 SystemDictionary::classes_do(&JvmtiGetLoadedClassesClosure::increment_with_loader); | |
312 Universe::basic_type_classes_do(&JvmtiGetLoadedClassesClosure::increment_for_basic_type_arrays); | |
313 // Next, fill in the classes | |
314 closure.allocate(); | |
315 SystemDictionary::classes_do(&JvmtiGetLoadedClassesClosure::add_with_loader); | |
316 Universe::basic_type_classes_do(&JvmtiGetLoadedClassesClosure::add_for_basic_type_arrays); | |
317 // Drop the SystemDictionary_lock, so the results could be wrong from here, | |
318 // but we still have a snapshot. | |
319 } | |
320 // Post results | |
321 jclass* result_list; | |
322 jvmtiError err = env->Allocate(closure.get_count() * sizeof(jclass), | |
323 (unsigned char**)&result_list); | |
324 if (err != JVMTI_ERROR_NONE) { | |
325 return err; | |
326 } | |
327 closure.extract(env, result_list); | |
328 *classCountPtr = closure.get_count(); | |
329 *classesPtr = result_list; | |
330 return JVMTI_ERROR_NONE; | |
331 } |