|
1 /* |
|
2 * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. |
|
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 * |
|
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
|
20 * CA 95054 USA or visit www.sun.com if you need additional information or |
|
21 * have any questions. |
|
22 * |
|
23 */ |
|
24 |
|
25 #include "incls/_precompiled.incl" |
|
26 #include "incls/_classLoader.cpp.incl" |
|
27 |
|
28 |
|
29 // Entry points in zip.dll for loading zip/jar file entries |
|
30 |
|
31 typedef void * * (JNICALL *ZipOpen_t)(const char *name, char **pmsg); |
|
32 typedef void (JNICALL *ZipClose_t)(jzfile *zip); |
|
33 typedef jzentry* (JNICALL *FindEntry_t)(jzfile *zip, const char *name, jint *sizeP, jint *nameLen); |
|
34 typedef jboolean (JNICALL *ReadEntry_t)(jzfile *zip, jzentry *entry, unsigned char *buf, char *namebuf); |
|
35 typedef jboolean (JNICALL *ReadMappedEntry_t)(jzfile *zip, jzentry *entry, unsigned char **buf, char *namebuf); |
|
36 typedef jzentry* (JNICALL *GetNextEntry_t)(jzfile *zip, jint n); |
|
37 |
|
38 static ZipOpen_t ZipOpen = NULL; |
|
39 static ZipClose_t ZipClose = NULL; |
|
40 static FindEntry_t FindEntry = NULL; |
|
41 static ReadEntry_t ReadEntry = NULL; |
|
42 static ReadMappedEntry_t ReadMappedEntry = NULL; |
|
43 static GetNextEntry_t GetNextEntry = NULL; |
|
44 static canonicalize_fn_t CanonicalizeEntry = NULL; |
|
45 |
|
46 // Globals |
|
47 |
|
48 PerfCounter* ClassLoader::_perf_accumulated_time = NULL; |
|
49 PerfCounter* ClassLoader::_perf_classes_inited = NULL; |
|
50 PerfCounter* ClassLoader::_perf_class_init_time = NULL; |
|
51 PerfCounter* ClassLoader::_perf_class_verify_time = NULL; |
|
52 PerfCounter* ClassLoader::_perf_classes_linked = NULL; |
|
53 PerfCounter* ClassLoader::_perf_class_link_time = NULL; |
|
54 PerfCounter* ClassLoader::_sync_systemLoaderLockContentionRate = NULL; |
|
55 PerfCounter* ClassLoader::_sync_nonSystemLoaderLockContentionRate = NULL; |
|
56 PerfCounter* ClassLoader::_sync_JVMFindLoadedClassLockFreeCounter = NULL; |
|
57 PerfCounter* ClassLoader::_sync_JVMDefineClassLockFreeCounter = NULL; |
|
58 PerfCounter* ClassLoader::_sync_JNIDefineClassLockFreeCounter = NULL; |
|
59 PerfCounter* ClassLoader::_unsafe_defineClassCallCounter = NULL; |
|
60 PerfCounter* ClassLoader::_isUnsyncloadClass = NULL; |
|
61 PerfCounter* ClassLoader::_load_instance_class_failCounter = NULL; |
|
62 |
|
63 ClassPathEntry* ClassLoader::_first_entry = NULL; |
|
64 ClassPathEntry* ClassLoader::_last_entry = NULL; |
|
65 PackageHashtable* ClassLoader::_package_hash_table = NULL; |
|
66 |
|
67 // helper routines |
|
68 bool string_starts_with(const char* str, const char* str_to_find) { |
|
69 size_t str_len = strlen(str); |
|
70 size_t str_to_find_len = strlen(str_to_find); |
|
71 if (str_to_find_len > str_len) { |
|
72 return false; |
|
73 } |
|
74 return (strncmp(str, str_to_find, str_to_find_len) == 0); |
|
75 } |
|
76 |
|
77 bool string_ends_with(const char* str, const char* str_to_find) { |
|
78 size_t str_len = strlen(str); |
|
79 size_t str_to_find_len = strlen(str_to_find); |
|
80 if (str_to_find_len > str_len) { |
|
81 return false; |
|
82 } |
|
83 return (strncmp(str + (str_len - str_to_find_len), str_to_find, str_to_find_len) == 0); |
|
84 } |
|
85 |
|
86 |
|
87 MetaIndex::MetaIndex(char** meta_package_names, int num_meta_package_names) { |
|
88 if (num_meta_package_names == 0) { |
|
89 _meta_package_names = NULL; |
|
90 _num_meta_package_names = 0; |
|
91 } else { |
|
92 _meta_package_names = NEW_C_HEAP_ARRAY(char*, num_meta_package_names); |
|
93 _num_meta_package_names = num_meta_package_names; |
|
94 memcpy(_meta_package_names, meta_package_names, num_meta_package_names * sizeof(char*)); |
|
95 } |
|
96 } |
|
97 |
|
98 |
|
99 MetaIndex::~MetaIndex() { |
|
100 FREE_C_HEAP_ARRAY(char*, _meta_package_names); |
|
101 } |
|
102 |
|
103 |
|
104 bool MetaIndex::may_contain(const char* class_name) { |
|
105 if ( _num_meta_package_names == 0) { |
|
106 return false; |
|
107 } |
|
108 size_t class_name_len = strlen(class_name); |
|
109 for (int i = 0; i < _num_meta_package_names; i++) { |
|
110 char* pkg = _meta_package_names[i]; |
|
111 size_t pkg_len = strlen(pkg); |
|
112 size_t min_len = MIN2(class_name_len, pkg_len); |
|
113 if (!strncmp(class_name, pkg, min_len)) { |
|
114 return true; |
|
115 } |
|
116 } |
|
117 return false; |
|
118 } |
|
119 |
|
120 |
|
121 ClassPathEntry::ClassPathEntry() { |
|
122 set_next(NULL); |
|
123 } |
|
124 |
|
125 |
|
126 bool ClassPathEntry::is_lazy() { |
|
127 return false; |
|
128 } |
|
129 |
|
130 ClassPathDirEntry::ClassPathDirEntry(char* dir) : ClassPathEntry() { |
|
131 _dir = NEW_C_HEAP_ARRAY(char, strlen(dir)+1); |
|
132 strcpy(_dir, dir); |
|
133 } |
|
134 |
|
135 |
|
136 ClassFileStream* ClassPathDirEntry::open_stream(const char* name) { |
|
137 // construct full path name |
|
138 char path[JVM_MAXPATHLEN]; |
|
139 if (jio_snprintf(path, sizeof(path), "%s%s%s", _dir, os::file_separator(), name) == -1) { |
|
140 return NULL; |
|
141 } |
|
142 // check if file exists |
|
143 struct stat st; |
|
144 if (os::stat(path, &st) == 0) { |
|
145 // found file, open it |
|
146 int file_handle = hpi::open(path, 0, 0); |
|
147 if (file_handle != -1) { |
|
148 // read contents into resource array |
|
149 u1* buffer = NEW_RESOURCE_ARRAY(u1, st.st_size); |
|
150 size_t num_read = os::read(file_handle, (char*) buffer, st.st_size); |
|
151 // close file |
|
152 hpi::close(file_handle); |
|
153 // construct ClassFileStream |
|
154 if (num_read == (size_t)st.st_size) { |
|
155 return new ClassFileStream(buffer, st.st_size, _dir); // Resource allocated |
|
156 } |
|
157 } |
|
158 } |
|
159 return NULL; |
|
160 } |
|
161 |
|
162 |
|
163 ClassPathZipEntry::ClassPathZipEntry(jzfile* zip, const char* zip_name) : ClassPathEntry() { |
|
164 _zip = zip; |
|
165 _zip_name = NEW_C_HEAP_ARRAY(char, strlen(zip_name)+1); |
|
166 strcpy(_zip_name, zip_name); |
|
167 } |
|
168 |
|
169 ClassPathZipEntry::~ClassPathZipEntry() { |
|
170 if (ZipClose != NULL) { |
|
171 (*ZipClose)(_zip); |
|
172 } |
|
173 FREE_C_HEAP_ARRAY(char, _zip_name); |
|
174 } |
|
175 |
|
176 ClassFileStream* ClassPathZipEntry::open_stream(const char* name) { |
|
177 // enable call to C land |
|
178 JavaThread* thread = JavaThread::current(); |
|
179 ThreadToNativeFromVM ttn(thread); |
|
180 // check whether zip archive contains name |
|
181 jint filesize, name_len; |
|
182 jzentry* entry = (*FindEntry)(_zip, name, &filesize, &name_len); |
|
183 if (entry == NULL) return NULL; |
|
184 u1* buffer; |
|
185 char name_buf[128]; |
|
186 char* filename; |
|
187 if (name_len < 128) { |
|
188 filename = name_buf; |
|
189 } else { |
|
190 filename = NEW_RESOURCE_ARRAY(char, name_len + 1); |
|
191 } |
|
192 |
|
193 // file found, get pointer to class in mmaped jar file. |
|
194 if (ReadMappedEntry == NULL || |
|
195 !(*ReadMappedEntry)(_zip, entry, &buffer, filename)) { |
|
196 // mmaped access not available, perhaps due to compression, |
|
197 // read contents into resource array |
|
198 buffer = NEW_RESOURCE_ARRAY(u1, filesize); |
|
199 if (!(*ReadEntry)(_zip, entry, buffer, filename)) return NULL; |
|
200 } |
|
201 // return result |
|
202 return new ClassFileStream(buffer, filesize, _zip_name); // Resource allocated |
|
203 } |
|
204 |
|
205 // invoke function for each entry in the zip file |
|
206 void ClassPathZipEntry::contents_do(void f(const char* name, void* context), void* context) { |
|
207 JavaThread* thread = JavaThread::current(); |
|
208 HandleMark handle_mark(thread); |
|
209 ThreadToNativeFromVM ttn(thread); |
|
210 for (int n = 0; ; n++) { |
|
211 jzentry * ze = ((*GetNextEntry)(_zip, n)); |
|
212 if (ze == NULL) break; |
|
213 (*f)(ze->name, context); |
|
214 } |
|
215 } |
|
216 |
|
217 LazyClassPathEntry::LazyClassPathEntry(char* path, struct stat st) : ClassPathEntry() { |
|
218 _path = strdup(path); |
|
219 _st = st; |
|
220 _meta_index = NULL; |
|
221 _resolved_entry = NULL; |
|
222 } |
|
223 |
|
224 bool LazyClassPathEntry::is_jar_file() { |
|
225 return ((_st.st_mode & S_IFREG) == S_IFREG); |
|
226 } |
|
227 |
|
228 ClassPathEntry* LazyClassPathEntry::resolve_entry() { |
|
229 if (_resolved_entry != NULL) { |
|
230 return (ClassPathEntry*) _resolved_entry; |
|
231 } |
|
232 ClassPathEntry* new_entry = NULL; |
|
233 ClassLoader::create_class_path_entry(_path, _st, &new_entry, false); |
|
234 assert(new_entry != NULL, "earlier code should have caught this"); |
|
235 { |
|
236 ThreadCritical tc; |
|
237 if (_resolved_entry == NULL) { |
|
238 _resolved_entry = new_entry; |
|
239 return new_entry; |
|
240 } |
|
241 } |
|
242 assert(_resolved_entry != NULL, "bug in MT-safe resolution logic"); |
|
243 delete new_entry; |
|
244 return (ClassPathEntry*) _resolved_entry; |
|
245 } |
|
246 |
|
247 ClassFileStream* LazyClassPathEntry::open_stream(const char* name) { |
|
248 if (_meta_index != NULL && |
|
249 !_meta_index->may_contain(name)) { |
|
250 return NULL; |
|
251 } |
|
252 return resolve_entry()->open_stream(name); |
|
253 } |
|
254 |
|
255 bool LazyClassPathEntry::is_lazy() { |
|
256 return true; |
|
257 } |
|
258 |
|
259 static void print_meta_index(LazyClassPathEntry* entry, |
|
260 GrowableArray<char*>& meta_packages) { |
|
261 tty->print("[Meta index for %s=", entry->name()); |
|
262 for (int i = 0; i < meta_packages.length(); i++) { |
|
263 if (i > 0) tty->print(" "); |
|
264 tty->print(meta_packages.at(i)); |
|
265 } |
|
266 tty->print_cr("]"); |
|
267 } |
|
268 |
|
269 |
|
270 void ClassLoader::setup_meta_index() { |
|
271 // Set up meta index which allows us to open boot jars lazily if |
|
272 // class data sharing is enabled |
|
273 const char* known_version = "% VERSION 2"; |
|
274 char* meta_index_path = Arguments::get_meta_index_path(); |
|
275 char* meta_index_dir = Arguments::get_meta_index_dir(); |
|
276 FILE* file = fopen(meta_index_path, "r"); |
|
277 int line_no = 0; |
|
278 if (file != NULL) { |
|
279 ResourceMark rm; |
|
280 LazyClassPathEntry* cur_entry = NULL; |
|
281 GrowableArray<char*> boot_class_path_packages(10); |
|
282 char package_name[256]; |
|
283 bool skipCurrentJar = false; |
|
284 while (fgets(package_name, sizeof(package_name), file) != NULL) { |
|
285 ++line_no; |
|
286 // Remove trailing newline |
|
287 package_name[strlen(package_name) - 1] = '\0'; |
|
288 switch(package_name[0]) { |
|
289 case '%': |
|
290 { |
|
291 if ((line_no == 1) && (strcmp(package_name, known_version) != 0)) { |
|
292 if (TraceClassLoading && Verbose) { |
|
293 tty->print("[Unsupported meta index version]"); |
|
294 } |
|
295 fclose(file); |
|
296 return; |
|
297 } |
|
298 } |
|
299 |
|
300 // These directives indicate jar files which contain only |
|
301 // classes, only non-classfile resources, or a combination of |
|
302 // the two. See src/share/classes/sun/misc/MetaIndex.java and |
|
303 // make/tools/MetaIndex/BuildMetaIndex.java in the J2SE |
|
304 // workspace. |
|
305 case '#': |
|
306 case '!': |
|
307 case '@': |
|
308 { |
|
309 // Hand off current packages to current lazy entry (if any) |
|
310 if ((cur_entry != NULL) && |
|
311 (boot_class_path_packages.length() > 0)) { |
|
312 if (TraceClassLoading && Verbose) { |
|
313 print_meta_index(cur_entry, boot_class_path_packages); |
|
314 } |
|
315 MetaIndex* index = new MetaIndex(boot_class_path_packages.adr_at(0), |
|
316 boot_class_path_packages.length()); |
|
317 cur_entry->set_meta_index(index); |
|
318 } |
|
319 cur_entry = NULL; |
|
320 boot_class_path_packages.clear(); |
|
321 |
|
322 // Find lazy entry corresponding to this jar file |
|
323 for (ClassPathEntry* entry = _first_entry; entry != NULL; entry = entry->next()) { |
|
324 if (entry->is_lazy() && |
|
325 string_starts_with(entry->name(), meta_index_dir) && |
|
326 string_ends_with(entry->name(), &package_name[2])) { |
|
327 cur_entry = (LazyClassPathEntry*) entry; |
|
328 break; |
|
329 } |
|
330 } |
|
331 |
|
332 // If the first character is '@', it indicates the following jar |
|
333 // file is a resource only jar file in which case, we should skip |
|
334 // reading the subsequent entries since the resource loading is |
|
335 // totally handled by J2SE side. |
|
336 if (package_name[0] == '@') { |
|
337 if (cur_entry != NULL) { |
|
338 cur_entry->set_meta_index(new MetaIndex(NULL, 0)); |
|
339 } |
|
340 cur_entry = NULL; |
|
341 skipCurrentJar = true; |
|
342 } else { |
|
343 skipCurrentJar = false; |
|
344 } |
|
345 |
|
346 break; |
|
347 } |
|
348 |
|
349 default: |
|
350 { |
|
351 if (!skipCurrentJar && cur_entry != NULL) { |
|
352 char* new_name = strdup(package_name); |
|
353 boot_class_path_packages.append(new_name); |
|
354 } |
|
355 } |
|
356 } |
|
357 } |
|
358 // Hand off current packages to current lazy entry (if any) |
|
359 if ((cur_entry != NULL) && |
|
360 (boot_class_path_packages.length() > 0)) { |
|
361 if (TraceClassLoading && Verbose) { |
|
362 print_meta_index(cur_entry, boot_class_path_packages); |
|
363 } |
|
364 MetaIndex* index = new MetaIndex(boot_class_path_packages.adr_at(0), |
|
365 boot_class_path_packages.length()); |
|
366 cur_entry->set_meta_index(index); |
|
367 } |
|
368 fclose(file); |
|
369 } |
|
370 } |
|
371 |
|
372 void ClassLoader::setup_bootstrap_search_path() { |
|
373 assert(_first_entry == NULL, "should not setup bootstrap class search path twice"); |
|
374 char* sys_class_path = os::strdup(Arguments::get_sysclasspath()); |
|
375 if (TraceClassLoading && Verbose) { |
|
376 tty->print_cr("[Bootstrap loader class path=%s]", sys_class_path); |
|
377 } |
|
378 |
|
379 int len = (int)strlen(sys_class_path); |
|
380 int end = 0; |
|
381 |
|
382 // Iterate over class path entries |
|
383 for (int start = 0; start < len; start = end) { |
|
384 while (sys_class_path[end] && sys_class_path[end] != os::path_separator()[0]) { |
|
385 end++; |
|
386 } |
|
387 char* path = NEW_C_HEAP_ARRAY(char, end-start+1); |
|
388 strncpy(path, &sys_class_path[start], end-start); |
|
389 path[end-start] = '\0'; |
|
390 update_class_path_entry_list(path, false); |
|
391 FREE_C_HEAP_ARRAY(char, path); |
|
392 while (sys_class_path[end] == os::path_separator()[0]) { |
|
393 end++; |
|
394 } |
|
395 } |
|
396 } |
|
397 |
|
398 void ClassLoader::create_class_path_entry(char *path, struct stat st, ClassPathEntry **new_entry, bool lazy) { |
|
399 JavaThread* thread = JavaThread::current(); |
|
400 if (lazy) { |
|
401 *new_entry = new LazyClassPathEntry(path, st); |
|
402 return; |
|
403 } |
|
404 if ((st.st_mode & S_IFREG) == S_IFREG) { |
|
405 // Regular file, should be a zip file |
|
406 // Canonicalized filename |
|
407 char canonical_path[JVM_MAXPATHLEN]; |
|
408 if (!get_canonical_path(path, canonical_path, JVM_MAXPATHLEN)) { |
|
409 // This matches the classic VM |
|
410 EXCEPTION_MARK; |
|
411 THROW_MSG(vmSymbols::java_io_IOException(), "Bad pathname"); |
|
412 } |
|
413 char* error_msg = NULL; |
|
414 jzfile* zip; |
|
415 { |
|
416 // enable call to C land |
|
417 ThreadToNativeFromVM ttn(thread); |
|
418 HandleMark hm(thread); |
|
419 zip = (*ZipOpen)(canonical_path, &error_msg); |
|
420 } |
|
421 if (zip != NULL && error_msg == NULL) { |
|
422 *new_entry = new ClassPathZipEntry(zip, path); |
|
423 if (TraceClassLoading) { |
|
424 tty->print_cr("[Opened %s]", path); |
|
425 } |
|
426 } else { |
|
427 ResourceMark rm(thread); |
|
428 char *msg; |
|
429 if (error_msg == NULL) { |
|
430 msg = NEW_RESOURCE_ARRAY(char, strlen(path) + 128); ; |
|
431 jio_snprintf(msg, strlen(path) + 127, "error in opening JAR file %s", path); |
|
432 } else { |
|
433 int len = (int)(strlen(path) + strlen(error_msg) + 128); |
|
434 msg = NEW_RESOURCE_ARRAY(char, len); ; |
|
435 jio_snprintf(msg, len - 1, "error in opening JAR file <%s> %s", error_msg, path); |
|
436 } |
|
437 EXCEPTION_MARK; |
|
438 THROW_MSG(vmSymbols::java_lang_ClassNotFoundException(), msg); |
|
439 } |
|
440 } else { |
|
441 // Directory |
|
442 *new_entry = new ClassPathDirEntry(path); |
|
443 if (TraceClassLoading) { |
|
444 tty->print_cr("[Path %s]", path); |
|
445 } |
|
446 } |
|
447 } |
|
448 |
|
449 |
|
450 // Create a class path zip entry for a given path (return NULL if not found |
|
451 // or zip/JAR file cannot be opened) |
|
452 ClassPathZipEntry* ClassLoader::create_class_path_zip_entry(const char *path) { |
|
453 // check for a regular file |
|
454 struct stat st; |
|
455 if (os::stat(path, &st) == 0) { |
|
456 if ((st.st_mode & S_IFREG) == S_IFREG) { |
|
457 char orig_path[JVM_MAXPATHLEN]; |
|
458 char canonical_path[JVM_MAXPATHLEN]; |
|
459 |
|
460 strcpy(orig_path, path); |
|
461 if (get_canonical_path(orig_path, canonical_path, JVM_MAXPATHLEN)) { |
|
462 char* error_msg = NULL; |
|
463 jzfile* zip; |
|
464 { |
|
465 // enable call to C land |
|
466 JavaThread* thread = JavaThread::current(); |
|
467 ThreadToNativeFromVM ttn(thread); |
|
468 HandleMark hm(thread); |
|
469 zip = (*ZipOpen)(canonical_path, &error_msg); |
|
470 } |
|
471 if (zip != NULL && error_msg == NULL) { |
|
472 // create using canonical path |
|
473 return new ClassPathZipEntry(zip, canonical_path); |
|
474 } |
|
475 } |
|
476 } |
|
477 } |
|
478 return NULL; |
|
479 } |
|
480 |
|
481 // returns true if entry already on class path |
|
482 bool ClassLoader::contains_entry(ClassPathEntry *entry) { |
|
483 ClassPathEntry* e = _first_entry; |
|
484 while (e != NULL) { |
|
485 // assume zip entries have been canonicalized |
|
486 if (strcmp(entry->name(), e->name()) == 0) { |
|
487 return true; |
|
488 } |
|
489 e = e->next(); |
|
490 } |
|
491 return false; |
|
492 } |
|
493 |
|
494 void ClassLoader::add_to_list(ClassPathEntry *new_entry) { |
|
495 if (new_entry != NULL) { |
|
496 if (_last_entry == NULL) { |
|
497 _first_entry = _last_entry = new_entry; |
|
498 } else { |
|
499 _last_entry->set_next(new_entry); |
|
500 _last_entry = new_entry; |
|
501 } |
|
502 } |
|
503 } |
|
504 |
|
505 void ClassLoader::update_class_path_entry_list(const char *path, |
|
506 bool check_for_duplicates) { |
|
507 struct stat st; |
|
508 if (os::stat((char *)path, &st) == 0) { |
|
509 // File or directory found |
|
510 ClassPathEntry* new_entry = NULL; |
|
511 create_class_path_entry((char *)path, st, &new_entry, LazyBootClassLoader); |
|
512 // The kernel VM adds dynamically to the end of the classloader path and |
|
513 // doesn't reorder the bootclasspath which would break java.lang.Package |
|
514 // (see PackageInfo). |
|
515 // Add new entry to linked list |
|
516 if (!check_for_duplicates || !contains_entry(new_entry)) { |
|
517 add_to_list(new_entry); |
|
518 } |
|
519 } |
|
520 } |
|
521 |
|
522 void ClassLoader::print_bootclasspath() { |
|
523 ClassPathEntry* e = _first_entry; |
|
524 tty->print("[bootclasspath= "); |
|
525 while (e != NULL) { |
|
526 tty->print("%s ;", e->name()); |
|
527 e = e->next(); |
|
528 } |
|
529 tty->print_cr("]"); |
|
530 } |
|
531 |
|
532 void ClassLoader::load_zip_library() { |
|
533 assert(ZipOpen == NULL, "should not load zip library twice"); |
|
534 // First make sure native library is loaded |
|
535 os::native_java_library(); |
|
536 // Load zip library |
|
537 char path[JVM_MAXPATHLEN]; |
|
538 char ebuf[1024]; |
|
539 hpi::dll_build_name(path, sizeof(path), Arguments::get_dll_dir(), "zip"); |
|
540 void* handle = hpi::dll_load(path, ebuf, sizeof ebuf); |
|
541 if (handle == NULL) { |
|
542 vm_exit_during_initialization("Unable to load ZIP library", path); |
|
543 } |
|
544 // Lookup zip entry points |
|
545 ZipOpen = CAST_TO_FN_PTR(ZipOpen_t, hpi::dll_lookup(handle, "ZIP_Open")); |
|
546 ZipClose = CAST_TO_FN_PTR(ZipClose_t, hpi::dll_lookup(handle, "ZIP_Close")); |
|
547 FindEntry = CAST_TO_FN_PTR(FindEntry_t, hpi::dll_lookup(handle, "ZIP_FindEntry")); |
|
548 ReadEntry = CAST_TO_FN_PTR(ReadEntry_t, hpi::dll_lookup(handle, "ZIP_ReadEntry")); |
|
549 ReadMappedEntry = CAST_TO_FN_PTR(ReadMappedEntry_t, hpi::dll_lookup(handle, "ZIP_ReadMappedEntry")); |
|
550 GetNextEntry = CAST_TO_FN_PTR(GetNextEntry_t, hpi::dll_lookup(handle, "ZIP_GetNextEntry")); |
|
551 |
|
552 // ZIP_Close is not exported on Windows in JDK5.0 so don't abort if ZIP_Close is NULL |
|
553 if (ZipOpen == NULL || FindEntry == NULL || ReadEntry == NULL || GetNextEntry == NULL) { |
|
554 vm_exit_during_initialization("Corrupted ZIP library", path); |
|
555 } |
|
556 |
|
557 // Lookup canonicalize entry in libjava.dll |
|
558 void *javalib_handle = os::native_java_library(); |
|
559 CanonicalizeEntry = CAST_TO_FN_PTR(canonicalize_fn_t, hpi::dll_lookup(javalib_handle, "Canonicalize")); |
|
560 // This lookup only works on 1.3. Do not check for non-null here |
|
561 } |
|
562 |
|
563 // PackageInfo data exists in order to support the java.lang.Package |
|
564 // class. A Package object provides information about a java package |
|
565 // (version, vendor, etc.) which originates in the manifest of the jar |
|
566 // file supplying the package. For application classes, the ClassLoader |
|
567 // object takes care of this. |
|
568 |
|
569 // For system (boot) classes, the Java code in the Package class needs |
|
570 // to be able to identify which source jar file contained the boot |
|
571 // class, so that it can extract the manifest from it. This table |
|
572 // identifies java packages with jar files in the boot classpath. |
|
573 |
|
574 // Because the boot classpath cannot change, the classpath index is |
|
575 // sufficient to identify the source jar file or directory. (Since |
|
576 // directories have no manifests, the directory name is not required, |
|
577 // but is available.) |
|
578 |
|
579 // When using sharing -- the pathnames of entries in the boot classpath |
|
580 // may not be the same at runtime as they were when the archive was |
|
581 // created (NFS, Samba, etc.). The actual files and directories named |
|
582 // in the classpath must be the same files, in the same order, even |
|
583 // though the exact name is not the same. |
|
584 |
|
585 class PackageInfo: public BasicHashtableEntry { |
|
586 public: |
|
587 const char* _pkgname; // Package name |
|
588 int _classpath_index; // Index of directory or JAR file loaded from |
|
589 |
|
590 PackageInfo* next() { |
|
591 return (PackageInfo*)BasicHashtableEntry::next(); |
|
592 } |
|
593 |
|
594 const char* pkgname() { return _pkgname; } |
|
595 void set_pkgname(char* pkgname) { _pkgname = pkgname; } |
|
596 |
|
597 const char* filename() { |
|
598 return ClassLoader::classpath_entry(_classpath_index)->name(); |
|
599 } |
|
600 |
|
601 void set_index(int index) { |
|
602 _classpath_index = index; |
|
603 } |
|
604 }; |
|
605 |
|
606 |
|
607 class PackageHashtable : public BasicHashtable { |
|
608 private: |
|
609 inline unsigned int compute_hash(const char *s, int n) { |
|
610 unsigned int val = 0; |
|
611 while (--n >= 0) { |
|
612 val = *s++ + 31 * val; |
|
613 } |
|
614 return val; |
|
615 } |
|
616 |
|
617 PackageInfo* bucket(int index) { |
|
618 return (PackageInfo*)BasicHashtable::bucket(index); |
|
619 } |
|
620 |
|
621 PackageInfo* get_entry(int index, unsigned int hash, |
|
622 const char* pkgname, size_t n) { |
|
623 for (PackageInfo* pp = bucket(index); pp != NULL; pp = pp->next()) { |
|
624 if (pp->hash() == hash && |
|
625 strncmp(pkgname, pp->pkgname(), n) == 0 && |
|
626 pp->pkgname()[n] == '\0') { |
|
627 return pp; |
|
628 } |
|
629 } |
|
630 return NULL; |
|
631 } |
|
632 |
|
633 public: |
|
634 PackageHashtable(int table_size) |
|
635 : BasicHashtable(table_size, sizeof(PackageInfo)) {} |
|
636 |
|
637 PackageHashtable(int table_size, HashtableBucket* t, int number_of_entries) |
|
638 : BasicHashtable(table_size, sizeof(PackageInfo), t, number_of_entries) {} |
|
639 |
|
640 PackageInfo* get_entry(const char* pkgname, int n) { |
|
641 unsigned int hash = compute_hash(pkgname, n); |
|
642 return get_entry(hash_to_index(hash), hash, pkgname, n); |
|
643 } |
|
644 |
|
645 PackageInfo* new_entry(char* pkgname, int n) { |
|
646 unsigned int hash = compute_hash(pkgname, n); |
|
647 PackageInfo* pp; |
|
648 pp = (PackageInfo*)BasicHashtable::new_entry(hash); |
|
649 pp->set_pkgname(pkgname); |
|
650 return pp; |
|
651 } |
|
652 |
|
653 void add_entry(PackageInfo* pp) { |
|
654 int index = hash_to_index(pp->hash()); |
|
655 BasicHashtable::add_entry(index, pp); |
|
656 } |
|
657 |
|
658 void copy_pkgnames(const char** packages) { |
|
659 int n = 0; |
|
660 for (int i = 0; i < table_size(); ++i) { |
|
661 for (PackageInfo* pp = bucket(i); pp != NULL; pp = pp->next()) { |
|
662 packages[n++] = pp->pkgname(); |
|
663 } |
|
664 } |
|
665 assert(n == number_of_entries(), "just checking"); |
|
666 } |
|
667 |
|
668 void copy_table(char** top, char* end, PackageHashtable* table); |
|
669 }; |
|
670 |
|
671 |
|
672 void PackageHashtable::copy_table(char** top, char* end, |
|
673 PackageHashtable* table) { |
|
674 // Copy (relocate) the table to the shared space. |
|
675 BasicHashtable::copy_table(top, end); |
|
676 |
|
677 // Calculate the space needed for the package name strings. |
|
678 int i; |
|
679 int n = 0; |
|
680 for (i = 0; i < table_size(); ++i) { |
|
681 for (PackageInfo* pp = table->bucket(i); |
|
682 pp != NULL; |
|
683 pp = pp->next()) { |
|
684 n += (int)(strlen(pp->pkgname()) + 1); |
|
685 } |
|
686 } |
|
687 if (*top + n + sizeof(intptr_t) >= end) { |
|
688 warning("\nThe shared miscellaneous data space is not large " |
|
689 "enough to \npreload requested classes. Use " |
|
690 "-XX:SharedMiscDataSize= to increase \nthe initial " |
|
691 "size of the miscellaneous data space.\n"); |
|
692 exit(2); |
|
693 } |
|
694 |
|
695 // Copy the table data (the strings) to the shared space. |
|
696 n = align_size_up(n, sizeof(HeapWord)); |
|
697 *(intptr_t*)(*top) = n; |
|
698 *top += sizeof(intptr_t); |
|
699 |
|
700 for (i = 0; i < table_size(); ++i) { |
|
701 for (PackageInfo* pp = table->bucket(i); |
|
702 pp != NULL; |
|
703 pp = pp->next()) { |
|
704 int n1 = (int)(strlen(pp->pkgname()) + 1); |
|
705 pp->set_pkgname((char*)memcpy(*top, pp->pkgname(), n1)); |
|
706 *top += n1; |
|
707 } |
|
708 } |
|
709 *top = (char*)align_size_up((intptr_t)*top, sizeof(HeapWord)); |
|
710 } |
|
711 |
|
712 |
|
713 void ClassLoader::copy_package_info_buckets(char** top, char* end) { |
|
714 _package_hash_table->copy_buckets(top, end); |
|
715 } |
|
716 |
|
717 void ClassLoader::copy_package_info_table(char** top, char* end) { |
|
718 _package_hash_table->copy_table(top, end, _package_hash_table); |
|
719 } |
|
720 |
|
721 |
|
722 PackageInfo* ClassLoader::lookup_package(const char *pkgname) { |
|
723 const char *cp = strrchr(pkgname, '/'); |
|
724 if (cp != NULL) { |
|
725 // Package prefix found |
|
726 int n = cp - pkgname + 1; |
|
727 return _package_hash_table->get_entry(pkgname, n); |
|
728 } |
|
729 return NULL; |
|
730 } |
|
731 |
|
732 |
|
733 bool ClassLoader::add_package(const char *pkgname, int classpath_index, TRAPS) { |
|
734 assert(pkgname != NULL, "just checking"); |
|
735 // Bootstrap loader no longer holds system loader lock obj serializing |
|
736 // load_instance_class and thereby add_package |
|
737 { |
|
738 MutexLocker ml(PackageTable_lock, THREAD); |
|
739 // First check for previously loaded entry |
|
740 PackageInfo* pp = lookup_package(pkgname); |
|
741 if (pp != NULL) { |
|
742 // Existing entry found, check source of package |
|
743 pp->set_index(classpath_index); |
|
744 return true; |
|
745 } |
|
746 |
|
747 const char *cp = strrchr(pkgname, '/'); |
|
748 if (cp != NULL) { |
|
749 // Package prefix found |
|
750 int n = cp - pkgname + 1; |
|
751 |
|
752 char* new_pkgname = NEW_C_HEAP_ARRAY(char, n + 1); |
|
753 if (new_pkgname == NULL) { |
|
754 return false; |
|
755 } |
|
756 |
|
757 memcpy(new_pkgname, pkgname, n); |
|
758 new_pkgname[n] = '\0'; |
|
759 pp = _package_hash_table->new_entry(new_pkgname, n); |
|
760 pp->set_index(classpath_index); |
|
761 |
|
762 // Insert into hash table |
|
763 _package_hash_table->add_entry(pp); |
|
764 } |
|
765 return true; |
|
766 } |
|
767 } |
|
768 |
|
769 |
|
770 oop ClassLoader::get_system_package(const char* name, TRAPS) { |
|
771 PackageInfo* pp; |
|
772 { |
|
773 MutexLocker ml(PackageTable_lock, THREAD); |
|
774 pp = lookup_package(name); |
|
775 } |
|
776 if (pp == NULL) { |
|
777 return NULL; |
|
778 } else { |
|
779 Handle p = java_lang_String::create_from_str(pp->filename(), THREAD); |
|
780 return p(); |
|
781 } |
|
782 } |
|
783 |
|
784 |
|
785 objArrayOop ClassLoader::get_system_packages(TRAPS) { |
|
786 ResourceMark rm(THREAD); |
|
787 int nof_entries; |
|
788 const char** packages; |
|
789 { |
|
790 MutexLocker ml(PackageTable_lock, THREAD); |
|
791 // Allocate resource char* array containing package names |
|
792 nof_entries = _package_hash_table->number_of_entries(); |
|
793 if ((packages = NEW_RESOURCE_ARRAY(const char*, nof_entries)) == NULL) { |
|
794 return NULL; |
|
795 } |
|
796 _package_hash_table->copy_pkgnames(packages); |
|
797 } |
|
798 // Allocate objArray and fill with java.lang.String |
|
799 objArrayOop r = oopFactory::new_objArray(SystemDictionary::string_klass(), |
|
800 nof_entries, CHECK_0); |
|
801 objArrayHandle result(THREAD, r); |
|
802 for (int i = 0; i < nof_entries; i++) { |
|
803 Handle str = java_lang_String::create_from_str(packages[i], CHECK_0); |
|
804 result->obj_at_put(i, str()); |
|
805 } |
|
806 |
|
807 return result(); |
|
808 } |
|
809 |
|
810 |
|
811 instanceKlassHandle ClassLoader::load_classfile(symbolHandle h_name, TRAPS) { |
|
812 VTuneClassLoadMarker clm; |
|
813 ResourceMark rm(THREAD); |
|
814 EventMark m("loading class " INTPTR_FORMAT, (address)h_name()); |
|
815 ThreadProfilerMark tpm(ThreadProfilerMark::classLoaderRegion); |
|
816 |
|
817 stringStream st; |
|
818 // st.print() uses too much stack space while handling a StackOverflowError |
|
819 // st.print("%s.class", h_name->as_utf8()); |
|
820 st.print_raw(h_name->as_utf8()); |
|
821 st.print_raw(".class"); |
|
822 char* name = st.as_string(); |
|
823 |
|
824 // Lookup stream for parsing .class file |
|
825 ClassFileStream* stream = NULL; |
|
826 int classpath_index = 0; |
|
827 { |
|
828 PerfTraceTime vmtimer(perf_accumulated_time()); |
|
829 ClassPathEntry* e = _first_entry; |
|
830 while (e != NULL) { |
|
831 stream = e->open_stream(name); |
|
832 if (stream != NULL) { |
|
833 break; |
|
834 } |
|
835 e = e->next(); |
|
836 ++classpath_index; |
|
837 } |
|
838 } |
|
839 |
|
840 instanceKlassHandle h(THREAD, klassOop(NULL)); |
|
841 if (stream != NULL) { |
|
842 |
|
843 // class file found, parse it |
|
844 ClassFileParser parser(stream); |
|
845 Handle class_loader; |
|
846 Handle protection_domain; |
|
847 symbolHandle parsed_name; |
|
848 instanceKlassHandle result = parser.parseClassFile(h_name, |
|
849 class_loader, |
|
850 protection_domain, |
|
851 parsed_name, |
|
852 CHECK_(h)); |
|
853 |
|
854 // add to package table |
|
855 if (add_package(name, classpath_index, THREAD)) { |
|
856 h = result; |
|
857 } |
|
858 } |
|
859 |
|
860 return h; |
|
861 } |
|
862 |
|
863 |
|
864 void ClassLoader::create_package_info_table(HashtableBucket *t, int length, |
|
865 int number_of_entries) { |
|
866 assert(_package_hash_table == NULL, "One package info table allowed."); |
|
867 assert(length == package_hash_table_size * sizeof(HashtableBucket), |
|
868 "bad shared package info size."); |
|
869 _package_hash_table = new PackageHashtable(package_hash_table_size, t, |
|
870 number_of_entries); |
|
871 } |
|
872 |
|
873 |
|
874 void ClassLoader::create_package_info_table() { |
|
875 assert(_package_hash_table == NULL, "shouldn't have one yet"); |
|
876 _package_hash_table = new PackageHashtable(package_hash_table_size); |
|
877 } |
|
878 |
|
879 |
|
880 // Initialize the class loader's access to methods in libzip. Parse and |
|
881 // process the boot classpath into a list ClassPathEntry objects. Once |
|
882 // this list has been created, it must not change order (see class PackageInfo) |
|
883 // it can be appended to and is by jvmti and the kernel vm. |
|
884 |
|
885 void ClassLoader::initialize() { |
|
886 assert(_package_hash_table == NULL, "should have been initialized by now."); |
|
887 EXCEPTION_MARK; |
|
888 |
|
889 if (UsePerfData) { |
|
890 // jvmstat performance counters |
|
891 NEWPERFTICKCOUNTER(_perf_accumulated_time, SUN_CLS, "time"); |
|
892 NEWPERFTICKCOUNTER(_perf_class_init_time, SUN_CLS, "classInitTime"); |
|
893 NEWPERFTICKCOUNTER(_perf_class_verify_time, SUN_CLS, "classVerifyTime"); |
|
894 NEWPERFTICKCOUNTER(_perf_class_link_time, SUN_CLS, "classLinkedTime"); |
|
895 |
|
896 NEWPERFEVENTCOUNTER(_perf_classes_inited, SUN_CLS, "initializedClasses"); |
|
897 NEWPERFEVENTCOUNTER(_perf_classes_linked, SUN_CLS, "linkedClasses"); |
|
898 |
|
899 // The following performance counters are added for measuring the impact |
|
900 // of the bug fix of 6365597. They are mainly focused on finding out |
|
901 // the behavior of system & user-defined classloader lock, whether |
|
902 // ClassLoader.loadClass/findClass is being called synchronized or not. |
|
903 // Also two additional counters are created to see whether 'UnsyncloadClass' |
|
904 // flag is being set or not and how many times load_instance_class call |
|
905 // fails with linkageError etc. |
|
906 NEWPERFEVENTCOUNTER(_sync_systemLoaderLockContentionRate, SUN_CLS, |
|
907 "systemLoaderLockContentionRate"); |
|
908 NEWPERFEVENTCOUNTER(_sync_nonSystemLoaderLockContentionRate, SUN_CLS, |
|
909 "nonSystemLoaderLockContentionRate"); |
|
910 NEWPERFEVENTCOUNTER(_sync_JVMFindLoadedClassLockFreeCounter, SUN_CLS, |
|
911 "jvmFindLoadedClassNoLockCalls"); |
|
912 NEWPERFEVENTCOUNTER(_sync_JVMDefineClassLockFreeCounter, SUN_CLS, |
|
913 "jvmDefineClassNoLockCalls"); |
|
914 |
|
915 NEWPERFEVENTCOUNTER(_sync_JNIDefineClassLockFreeCounter, SUN_CLS, |
|
916 "jniDefineClassNoLockCalls"); |
|
917 |
|
918 NEWPERFEVENTCOUNTER(_unsafe_defineClassCallCounter, SUN_CLS, |
|
919 "unsafeDefineClassCalls"); |
|
920 |
|
921 NEWPERFEVENTCOUNTER(_isUnsyncloadClass, SUN_CLS, "isUnsyncloadClassSet"); |
|
922 NEWPERFEVENTCOUNTER(_load_instance_class_failCounter, SUN_CLS, |
|
923 "loadInstanceClassFailRate"); |
|
924 |
|
925 // increment the isUnsyncloadClass counter if UnsyncloadClass is set. |
|
926 if (UnsyncloadClass) { |
|
927 _isUnsyncloadClass->inc(); |
|
928 } |
|
929 } |
|
930 |
|
931 // lookup zip library entry points |
|
932 load_zip_library(); |
|
933 // initialize search path |
|
934 setup_bootstrap_search_path(); |
|
935 if (LazyBootClassLoader) { |
|
936 // set up meta index which makes boot classpath initialization lazier |
|
937 setup_meta_index(); |
|
938 } |
|
939 } |
|
940 |
|
941 |
|
942 jlong ClassLoader::classloader_time_ms() { |
|
943 return UsePerfData ? |
|
944 Management::ticks_to_ms(_perf_accumulated_time->get_value()) : -1; |
|
945 } |
|
946 |
|
947 jlong ClassLoader::class_init_count() { |
|
948 return UsePerfData ? _perf_classes_inited->get_value() : -1; |
|
949 } |
|
950 |
|
951 jlong ClassLoader::class_init_time_ms() { |
|
952 return UsePerfData ? |
|
953 Management::ticks_to_ms(_perf_class_init_time->get_value()) : -1; |
|
954 } |
|
955 |
|
956 jlong ClassLoader::class_verify_time_ms() { |
|
957 return UsePerfData ? |
|
958 Management::ticks_to_ms(_perf_class_verify_time->get_value()) : -1; |
|
959 } |
|
960 |
|
961 jlong ClassLoader::class_link_count() { |
|
962 return UsePerfData ? _perf_classes_linked->get_value() : -1; |
|
963 } |
|
964 |
|
965 jlong ClassLoader::class_link_time_ms() { |
|
966 return UsePerfData ? |
|
967 Management::ticks_to_ms(_perf_class_link_time->get_value()) : -1; |
|
968 } |
|
969 |
|
970 int ClassLoader::compute_Object_vtable() { |
|
971 // hardwired for JDK1.2 -- would need to duplicate class file parsing |
|
972 // code to determine actual value from file |
|
973 // Would be value '11' if finals were in vtable |
|
974 int JDK_1_2_Object_vtable_size = 5; |
|
975 return JDK_1_2_Object_vtable_size * vtableEntry::size(); |
|
976 } |
|
977 |
|
978 |
|
979 void classLoader_init() { |
|
980 ClassLoader::initialize(); |
|
981 } |
|
982 |
|
983 |
|
984 bool ClassLoader::get_canonical_path(char* orig, char* out, int len) { |
|
985 assert(orig != NULL && out != NULL && len > 0, "bad arguments"); |
|
986 if (CanonicalizeEntry != NULL) { |
|
987 JNIEnv* env = JavaThread::current()->jni_environment(); |
|
988 if ((CanonicalizeEntry)(env, hpi::native_path(orig), out, len) < 0) { |
|
989 return false; |
|
990 } |
|
991 } else { |
|
992 // On JDK 1.2.2 the Canonicalize does not exist, so just do nothing |
|
993 strncpy(out, orig, len); |
|
994 out[len - 1] = '\0'; |
|
995 } |
|
996 return true; |
|
997 } |
|
998 |
|
999 #ifndef PRODUCT |
|
1000 |
|
1001 void ClassLoader::verify() { |
|
1002 _package_hash_table->verify(); |
|
1003 } |
|
1004 |
|
1005 |
|
1006 // CompileTheWorld |
|
1007 // |
|
1008 // Iterates over all class path entries and forces compilation of all methods |
|
1009 // in all classes found. Currently, only zip/jar archives are searched. |
|
1010 // |
|
1011 // The classes are loaded by the Java level bootstrap class loader, and the |
|
1012 // initializer is called. If DelayCompilationDuringStartup is true (default), |
|
1013 // the interpreter will run the initialization code. Note that forcing |
|
1014 // initialization in this way could potentially lead to initialization order |
|
1015 // problems, in which case we could just force the initialization bit to be set. |
|
1016 |
|
1017 |
|
1018 // We need to iterate over the contents of a zip/jar file, so we replicate the |
|
1019 // jzcell and jzfile definitions from zip_util.h but rename jzfile to real_jzfile, |
|
1020 // since jzfile already has a void* definition. |
|
1021 // |
|
1022 // Note that this is only used in debug mode. |
|
1023 // |
|
1024 // HotSpot integration note: |
|
1025 // Matches zip_util.h 1.14 99/06/01 from jdk1.3 beta H build |
|
1026 |
|
1027 |
|
1028 // JDK 1.3 version |
|
1029 typedef struct real_jzentry13 { /* Zip file entry */ |
|
1030 char *name; /* entry name */ |
|
1031 jint time; /* modification time */ |
|
1032 jint size; /* size of uncompressed data */ |
|
1033 jint csize; /* size of compressed data (zero if uncompressed) */ |
|
1034 jint crc; /* crc of uncompressed data */ |
|
1035 char *comment; /* optional zip file comment */ |
|
1036 jbyte *extra; /* optional extra data */ |
|
1037 jint pos; /* position of LOC header (if negative) or data */ |
|
1038 } real_jzentry13; |
|
1039 |
|
1040 typedef struct real_jzfile13 { /* Zip file */ |
|
1041 char *name; /* zip file name */ |
|
1042 jint refs; /* number of active references */ |
|
1043 jint fd; /* open file descriptor */ |
|
1044 void *lock; /* read lock */ |
|
1045 char *comment; /* zip file comment */ |
|
1046 char *msg; /* zip error message */ |
|
1047 void *entries; /* array of hash cells */ |
|
1048 jint total; /* total number of entries */ |
|
1049 unsigned short *table; /* Hash chain heads: indexes into entries */ |
|
1050 jint tablelen; /* number of hash eads */ |
|
1051 real_jzfile13 *next; /* next zip file in search list */ |
|
1052 jzentry *cache; /* we cache the most recently freed jzentry */ |
|
1053 /* Information on metadata names in META-INF directory */ |
|
1054 char **metanames; /* array of meta names (may have null names) */ |
|
1055 jint metacount; /* number of slots in metanames array */ |
|
1056 /* If there are any per-entry comments, they are in the comments array */ |
|
1057 char **comments; |
|
1058 } real_jzfile13; |
|
1059 |
|
1060 // JDK 1.2 version |
|
1061 typedef struct real_jzentry12 { /* Zip file entry */ |
|
1062 char *name; /* entry name */ |
|
1063 jint time; /* modification time */ |
|
1064 jint size; /* size of uncompressed data */ |
|
1065 jint csize; /* size of compressed data (zero if uncompressed) */ |
|
1066 jint crc; /* crc of uncompressed data */ |
|
1067 char *comment; /* optional zip file comment */ |
|
1068 jbyte *extra; /* optional extra data */ |
|
1069 jint pos; /* position of LOC header (if negative) or data */ |
|
1070 struct real_jzentry12 *next; /* next entry in hash table */ |
|
1071 } real_jzentry12; |
|
1072 |
|
1073 typedef struct real_jzfile12 { /* Zip file */ |
|
1074 char *name; /* zip file name */ |
|
1075 jint refs; /* number of active references */ |
|
1076 jint fd; /* open file descriptor */ |
|
1077 void *lock; /* read lock */ |
|
1078 char *comment; /* zip file comment */ |
|
1079 char *msg; /* zip error message */ |
|
1080 real_jzentry12 *entries; /* array of zip entries */ |
|
1081 jint total; /* total number of entries */ |
|
1082 real_jzentry12 **table; /* hash table of entries */ |
|
1083 jint tablelen; /* number of buckets */ |
|
1084 jzfile *next; /* next zip file in search list */ |
|
1085 } real_jzfile12; |
|
1086 |
|
1087 |
|
1088 void ClassPathDirEntry::compile_the_world(Handle loader, TRAPS) { |
|
1089 // For now we only compile all methods in all classes in zip/jar files |
|
1090 tty->print_cr("CompileTheWorld : Skipped classes in %s", _dir); |
|
1091 tty->cr(); |
|
1092 } |
|
1093 |
|
1094 |
|
1095 bool ClassPathDirEntry::is_rt_jar() { |
|
1096 return false; |
|
1097 } |
|
1098 |
|
1099 void ClassPathZipEntry::compile_the_world(Handle loader, TRAPS) { |
|
1100 if (JDK_Version::is_jdk12x_version()) { |
|
1101 compile_the_world12(loader, THREAD); |
|
1102 } else { |
|
1103 compile_the_world13(loader, THREAD); |
|
1104 } |
|
1105 if (HAS_PENDING_EXCEPTION) { |
|
1106 if (PENDING_EXCEPTION->is_a(SystemDictionary::OutOfMemoryError_klass())) { |
|
1107 CLEAR_PENDING_EXCEPTION; |
|
1108 tty->print_cr("\nCompileTheWorld : Ran out of memory\n"); |
|
1109 size_t used = Universe::heap()->permanent_used(); |
|
1110 size_t capacity = Universe::heap()->permanent_capacity(); |
|
1111 tty->print_cr("Permanent generation used %dK of %dK", used/K, capacity/K); |
|
1112 tty->print_cr("Increase size by setting e.g. -XX:MaxPermSize=%dK\n", capacity*2/K); |
|
1113 } else { |
|
1114 tty->print_cr("\nCompileTheWorld : Unexpected exception occurred\n"); |
|
1115 } |
|
1116 } |
|
1117 } |
|
1118 |
|
1119 // Version that works for JDK 1.3.x |
|
1120 void ClassPathZipEntry::compile_the_world13(Handle loader, TRAPS) { |
|
1121 real_jzfile13* zip = (real_jzfile13*) _zip; |
|
1122 tty->print_cr("CompileTheWorld : Compiling all classes in %s", zip->name); |
|
1123 tty->cr(); |
|
1124 // Iterate over all entries in zip file |
|
1125 for (int n = 0; ; n++) { |
|
1126 real_jzentry13 * ze = (real_jzentry13 *)((*GetNextEntry)(_zip, n)); |
|
1127 if (ze == NULL) break; |
|
1128 ClassLoader::compile_the_world_in(ze->name, loader, CHECK); |
|
1129 } |
|
1130 } |
|
1131 |
|
1132 |
|
1133 // Version that works for JDK 1.2.x |
|
1134 void ClassPathZipEntry::compile_the_world12(Handle loader, TRAPS) { |
|
1135 real_jzfile12* zip = (real_jzfile12*) _zip; |
|
1136 tty->print_cr("CompileTheWorld : Compiling all classes in %s", zip->name); |
|
1137 tty->cr(); |
|
1138 // Iterate over all entries in zip file |
|
1139 for (int n = 0; ; n++) { |
|
1140 real_jzentry12 * ze = (real_jzentry12 *)((*GetNextEntry)(_zip, n)); |
|
1141 if (ze == NULL) break; |
|
1142 ClassLoader::compile_the_world_in(ze->name, loader, CHECK); |
|
1143 } |
|
1144 } |
|
1145 |
|
1146 bool ClassPathZipEntry::is_rt_jar() { |
|
1147 if (JDK_Version::is_jdk12x_version()) { |
|
1148 return is_rt_jar12(); |
|
1149 } else { |
|
1150 return is_rt_jar13(); |
|
1151 } |
|
1152 } |
|
1153 |
|
1154 // JDK 1.3 version |
|
1155 bool ClassPathZipEntry::is_rt_jar13() { |
|
1156 real_jzfile13* zip = (real_jzfile13*) _zip; |
|
1157 int len = (int)strlen(zip->name); |
|
1158 // Check whether zip name ends in "rt.jar" |
|
1159 // This will match other archives named rt.jar as well, but this is |
|
1160 // only used for debugging. |
|
1161 return (len >= 6) && (strcasecmp(zip->name + len - 6, "rt.jar") == 0); |
|
1162 } |
|
1163 |
|
1164 // JDK 1.2 version |
|
1165 bool ClassPathZipEntry::is_rt_jar12() { |
|
1166 real_jzfile12* zip = (real_jzfile12*) _zip; |
|
1167 int len = (int)strlen(zip->name); |
|
1168 // Check whether zip name ends in "rt.jar" |
|
1169 // This will match other archives named rt.jar as well, but this is |
|
1170 // only used for debugging. |
|
1171 return (len >= 6) && (strcasecmp(zip->name + len - 6, "rt.jar") == 0); |
|
1172 } |
|
1173 |
|
1174 void LazyClassPathEntry::compile_the_world(Handle loader, TRAPS) { |
|
1175 resolve_entry()->compile_the_world(loader, CHECK); |
|
1176 } |
|
1177 |
|
1178 bool LazyClassPathEntry::is_rt_jar() { |
|
1179 return resolve_entry()->is_rt_jar(); |
|
1180 } |
|
1181 |
|
1182 void ClassLoader::compile_the_world() { |
|
1183 EXCEPTION_MARK; |
|
1184 HandleMark hm(THREAD); |
|
1185 ResourceMark rm(THREAD); |
|
1186 // Make sure we don't run with background compilation |
|
1187 BackgroundCompilation = false; |
|
1188 // Find bootstrap loader |
|
1189 Handle system_class_loader (THREAD, SystemDictionary::java_system_loader()); |
|
1190 // Iterate over all bootstrap class path entries |
|
1191 ClassPathEntry* e = _first_entry; |
|
1192 while (e != NULL) { |
|
1193 // We stop at rt.jar, unless it is the first bootstrap path entry |
|
1194 if (e->is_rt_jar() && e != _first_entry) break; |
|
1195 e->compile_the_world(system_class_loader, CATCH); |
|
1196 e = e->next(); |
|
1197 } |
|
1198 tty->print_cr("CompileTheWorld : Done"); |
|
1199 { |
|
1200 // Print statistics as if before normal exit: |
|
1201 extern void print_statistics(); |
|
1202 print_statistics(); |
|
1203 } |
|
1204 vm_exit(0); |
|
1205 } |
|
1206 |
|
1207 int ClassLoader::_compile_the_world_counter = 0; |
|
1208 |
|
1209 void ClassLoader::compile_the_world_in(char* name, Handle loader, TRAPS) { |
|
1210 int len = (int)strlen(name); |
|
1211 if (len > 6 && strcmp(".class", name + len - 6) == 0) { |
|
1212 // We have a .class file |
|
1213 char buffer[2048]; |
|
1214 strncpy(buffer, name, len - 6); |
|
1215 buffer[len-6] = 0; |
|
1216 // If the file has a period after removing .class, it's not really a |
|
1217 // valid class file. The class loader will check everything else. |
|
1218 if (strchr(buffer, '.') == NULL) { |
|
1219 _compile_the_world_counter++; |
|
1220 if (_compile_the_world_counter >= CompileTheWorldStartAt && _compile_the_world_counter <= CompileTheWorldStopAt) { |
|
1221 // Construct name without extension |
|
1222 symbolHandle sym = oopFactory::new_symbol_handle(buffer, CHECK); |
|
1223 // Use loader to load and initialize class |
|
1224 klassOop ik = SystemDictionary::resolve_or_null(sym, loader, Handle(), THREAD); |
|
1225 instanceKlassHandle k (THREAD, ik); |
|
1226 if (k.not_null() && !HAS_PENDING_EXCEPTION) { |
|
1227 k->initialize(THREAD); |
|
1228 } |
|
1229 bool exception_occurred = HAS_PENDING_EXCEPTION; |
|
1230 CLEAR_PENDING_EXCEPTION; |
|
1231 if (k.is_null() || (exception_occurred && !CompileTheWorldIgnoreInitErrors)) { |
|
1232 // If something went wrong (e.g. ExceptionInInitializerError) we skip this class |
|
1233 tty->print_cr("CompileTheWorld (%d) : Skipping %s", _compile_the_world_counter, buffer); |
|
1234 } else { |
|
1235 tty->print_cr("CompileTheWorld (%d) : %s", _compile_the_world_counter, buffer); |
|
1236 // Preload all classes to get around uncommon traps |
|
1237 if (CompileTheWorldPreloadClasses) { |
|
1238 constantPoolKlass::preload_and_initialize_all_classes(k->constants(), THREAD); |
|
1239 if (HAS_PENDING_EXCEPTION) { |
|
1240 // If something went wrong in preloading we just ignore it |
|
1241 CLEAR_PENDING_EXCEPTION; |
|
1242 tty->print_cr("Preloading failed for (%d) %s", _compile_the_world_counter, buffer); |
|
1243 } |
|
1244 } |
|
1245 // Iterate over all methods in class |
|
1246 for (int n = 0; n < k->methods()->length(); n++) { |
|
1247 methodHandle m (THREAD, methodOop(k->methods()->obj_at(n))); |
|
1248 if (CompilationPolicy::canBeCompiled(m)) { |
|
1249 // Force compilation |
|
1250 CompileBroker::compile_method(m, InvocationEntryBci, |
|
1251 methodHandle(), 0, "CTW", THREAD); |
|
1252 if (HAS_PENDING_EXCEPTION) { |
|
1253 CLEAR_PENDING_EXCEPTION; |
|
1254 tty->print_cr("CompileTheWorld (%d) : Skipping method: %s", _compile_the_world_counter, m->name()->as_C_string()); |
|
1255 } |
|
1256 if (TieredCompilation) { |
|
1257 // Clobber the first compile and force second tier compilation |
|
1258 m->clear_code(); |
|
1259 CompileBroker::compile_method(m, InvocationEntryBci, |
|
1260 methodHandle(), 0, "CTW", THREAD); |
|
1261 if (HAS_PENDING_EXCEPTION) { |
|
1262 CLEAR_PENDING_EXCEPTION; |
|
1263 tty->print_cr("CompileTheWorld (%d) : Skipping method: %s", _compile_the_world_counter, m->name()->as_C_string()); |
|
1264 } |
|
1265 } |
|
1266 } |
|
1267 } |
|
1268 } |
|
1269 } |
|
1270 } |
|
1271 } |
|
1272 } |
|
1273 |
|
1274 #endif //PRODUCT |