1 /* |
1 /* |
2 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
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 |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. |
7 * published by the Free Software Foundation. |
195 _dir = NEW_C_HEAP_ARRAY(char, strlen(dir)+1, mtClass); |
195 _dir = NEW_C_HEAP_ARRAY(char, strlen(dir)+1, mtClass); |
196 strcpy(_dir, dir); |
196 strcpy(_dir, dir); |
197 } |
197 } |
198 |
198 |
199 |
199 |
200 ClassFileStream* ClassPathDirEntry::open_stream(const char* name) { |
200 ClassFileStream* ClassPathDirEntry::open_stream(const char* name, TRAPS) { |
201 // construct full path name |
201 // construct full path name |
202 char path[JVM_MAXPATHLEN]; |
202 char path[JVM_MAXPATHLEN]; |
203 if (jio_snprintf(path, sizeof(path), "%s%s%s", _dir, os::file_separator(), name) == -1) { |
203 if (jio_snprintf(path, sizeof(path), "%s%s%s", _dir, os::file_separator(), name) == -1) { |
204 return NULL; |
204 return NULL; |
205 } |
205 } |
238 (*ZipClose)(_zip); |
238 (*ZipClose)(_zip); |
239 } |
239 } |
240 FREE_C_HEAP_ARRAY(char, _zip_name, mtClass); |
240 FREE_C_HEAP_ARRAY(char, _zip_name, mtClass); |
241 } |
241 } |
242 |
242 |
243 ClassFileStream* ClassPathZipEntry::open_stream(const char* name) { |
243 ClassFileStream* ClassPathZipEntry::open_stream(const char* name, TRAPS) { |
244 // enable call to C land |
244 // enable call to C land |
245 JavaThread* thread = JavaThread::current(); |
245 JavaThread* thread = JavaThread::current(); |
246 ThreadToNativeFromVM ttn(thread); |
246 ThreadToNativeFromVM ttn(thread); |
247 // check whether zip archive contains name |
247 // check whether zip archive contains name |
248 jint filesize, name_len; |
248 jint filesize, name_len; |
282 if (ze == NULL) break; |
282 if (ze == NULL) break; |
283 (*f)(ze->name, context); |
283 (*f)(ze->name, context); |
284 } |
284 } |
285 } |
285 } |
286 |
286 |
287 LazyClassPathEntry::LazyClassPathEntry(char* path, struct stat st) : ClassPathEntry() { |
287 LazyClassPathEntry::LazyClassPathEntry(char* path, const struct stat* st) : ClassPathEntry() { |
288 _path = strdup(path); |
288 _path = strdup(path); |
289 _st = st; |
289 _st = *st; |
290 _meta_index = NULL; |
290 _meta_index = NULL; |
291 _resolved_entry = NULL; |
291 _resolved_entry = NULL; |
|
292 _has_error = false; |
292 } |
293 } |
293 |
294 |
294 bool LazyClassPathEntry::is_jar_file() { |
295 bool LazyClassPathEntry::is_jar_file() { |
295 return ((_st.st_mode & S_IFREG) == S_IFREG); |
296 return ((_st.st_mode & S_IFREG) == S_IFREG); |
296 } |
297 } |
297 |
298 |
298 ClassPathEntry* LazyClassPathEntry::resolve_entry() { |
299 ClassPathEntry* LazyClassPathEntry::resolve_entry(TRAPS) { |
299 if (_resolved_entry != NULL) { |
300 if (_resolved_entry != NULL) { |
300 return (ClassPathEntry*) _resolved_entry; |
301 return (ClassPathEntry*) _resolved_entry; |
301 } |
302 } |
302 ClassPathEntry* new_entry = NULL; |
303 ClassPathEntry* new_entry = NULL; |
303 ClassLoader::create_class_path_entry(_path, _st, &new_entry, false); |
304 new_entry = ClassLoader::create_class_path_entry(_path, &_st, false, CHECK_NULL); |
304 assert(new_entry != NULL, "earlier code should have caught this"); |
|
305 { |
305 { |
306 ThreadCritical tc; |
306 ThreadCritical tc; |
307 if (_resolved_entry == NULL) { |
307 if (_resolved_entry == NULL) { |
308 _resolved_entry = new_entry; |
308 _resolved_entry = new_entry; |
309 return new_entry; |
309 return new_entry; |
312 assert(_resolved_entry != NULL, "bug in MT-safe resolution logic"); |
312 assert(_resolved_entry != NULL, "bug in MT-safe resolution logic"); |
313 delete new_entry; |
313 delete new_entry; |
314 return (ClassPathEntry*) _resolved_entry; |
314 return (ClassPathEntry*) _resolved_entry; |
315 } |
315 } |
316 |
316 |
317 ClassFileStream* LazyClassPathEntry::open_stream(const char* name) { |
317 ClassFileStream* LazyClassPathEntry::open_stream(const char* name, TRAPS) { |
318 if (_meta_index != NULL && |
318 if (_meta_index != NULL && |
319 !_meta_index->may_contain(name)) { |
319 !_meta_index->may_contain(name)) { |
320 return NULL; |
320 return NULL; |
321 } |
321 } |
322 return resolve_entry()->open_stream(name); |
322 if (_has_error) { |
|
323 return NULL; |
|
324 } |
|
325 ClassPathEntry* cpe = resolve_entry(THREAD); |
|
326 if (cpe == NULL) { |
|
327 _has_error = true; |
|
328 return NULL; |
|
329 } else { |
|
330 return cpe->open_stream(name, THREAD); |
|
331 } |
323 } |
332 } |
324 |
333 |
325 bool LazyClassPathEntry::is_lazy() { |
334 bool LazyClassPathEntry::is_lazy() { |
326 return true; |
335 return true; |
327 } |
336 } |
463 end++; |
472 end++; |
464 } |
473 } |
465 } |
474 } |
466 } |
475 } |
467 |
476 |
468 void ClassLoader::create_class_path_entry(char *path, struct stat st, ClassPathEntry **new_entry, bool lazy) { |
477 ClassPathEntry* ClassLoader::create_class_path_entry(char *path, const struct stat* st, bool lazy, TRAPS) { |
469 JavaThread* thread = JavaThread::current(); |
478 JavaThread* thread = JavaThread::current(); |
470 if (lazy) { |
479 if (lazy) { |
471 *new_entry = new LazyClassPathEntry(path, st); |
480 return new LazyClassPathEntry(path, st); |
472 return; |
481 } |
473 } |
482 ClassPathEntry* new_entry = NULL; |
474 if ((st.st_mode & S_IFREG) == S_IFREG) { |
483 if ((st->st_mode & S_IFREG) == S_IFREG) { |
475 // Regular file, should be a zip file |
484 // Regular file, should be a zip file |
476 // Canonicalized filename |
485 // Canonicalized filename |
477 char canonical_path[JVM_MAXPATHLEN]; |
486 char canonical_path[JVM_MAXPATHLEN]; |
478 if (!get_canonical_path(path, canonical_path, JVM_MAXPATHLEN)) { |
487 if (!get_canonical_path(path, canonical_path, JVM_MAXPATHLEN)) { |
479 // This matches the classic VM |
488 // This matches the classic VM |
480 EXCEPTION_MARK; |
489 THROW_MSG_(vmSymbols::java_io_IOException(), "Bad pathname", NULL); |
481 THROW_MSG(vmSymbols::java_io_IOException(), "Bad pathname"); |
|
482 } |
490 } |
483 char* error_msg = NULL; |
491 char* error_msg = NULL; |
484 jzfile* zip; |
492 jzfile* zip; |
485 { |
493 { |
486 // enable call to C land |
494 // enable call to C land |
487 ThreadToNativeFromVM ttn(thread); |
495 ThreadToNativeFromVM ttn(thread); |
488 HandleMark hm(thread); |
496 HandleMark hm(thread); |
489 zip = (*ZipOpen)(canonical_path, &error_msg); |
497 zip = (*ZipOpen)(canonical_path, &error_msg); |
490 } |
498 } |
491 if (zip != NULL && error_msg == NULL) { |
499 if (zip != NULL && error_msg == NULL) { |
492 *new_entry = new ClassPathZipEntry(zip, path); |
500 new_entry = new ClassPathZipEntry(zip, path); |
493 if (TraceClassLoading) { |
501 if (TraceClassLoading) { |
494 tty->print_cr("[Opened %s]", path); |
502 tty->print_cr("[Opened %s]", path); |
495 } |
503 } |
496 } else { |
504 } else { |
497 ResourceMark rm(thread); |
505 ResourceMark rm(thread); |
502 } else { |
510 } else { |
503 int len = (int)(strlen(path) + strlen(error_msg) + 128); |
511 int len = (int)(strlen(path) + strlen(error_msg) + 128); |
504 msg = NEW_RESOURCE_ARRAY(char, len); ; |
512 msg = NEW_RESOURCE_ARRAY(char, len); ; |
505 jio_snprintf(msg, len - 1, "error in opening JAR file <%s> %s", error_msg, path); |
513 jio_snprintf(msg, len - 1, "error in opening JAR file <%s> %s", error_msg, path); |
506 } |
514 } |
507 EXCEPTION_MARK; |
515 THROW_MSG_(vmSymbols::java_lang_ClassNotFoundException(), msg, NULL); |
508 THROW_MSG(vmSymbols::java_lang_ClassNotFoundException(), msg); |
|
509 } |
516 } |
510 } else { |
517 } else { |
511 // Directory |
518 // Directory |
512 *new_entry = new ClassPathDirEntry(path); |
519 new_entry = new ClassPathDirEntry(path); |
513 if (TraceClassLoading) { |
520 if (TraceClassLoading) { |
514 tty->print_cr("[Path %s]", path); |
521 tty->print_cr("[Path %s]", path); |
515 } |
522 } |
516 } |
523 } |
|
524 return new_entry; |
517 } |
525 } |
518 |
526 |
519 |
527 |
520 // Create a class path zip entry for a given path (return NULL if not found |
528 // Create a class path zip entry for a given path (return NULL if not found |
521 // or zip/JAR file cannot be opened) |
529 // or zip/JAR file cannot be opened) |
570 _last_entry = new_entry; |
578 _last_entry = new_entry; |
571 } |
579 } |
572 } |
580 } |
573 } |
581 } |
574 |
582 |
575 void ClassLoader::update_class_path_entry_list(const char *path, |
583 void ClassLoader::update_class_path_entry_list(char *path, |
576 bool check_for_duplicates) { |
584 bool check_for_duplicates) { |
577 struct stat st; |
585 struct stat st; |
578 if (os::stat((char *)path, &st) == 0) { |
586 if (os::stat(path, &st) == 0) { |
579 // File or directory found |
587 // File or directory found |
580 ClassPathEntry* new_entry = NULL; |
588 ClassPathEntry* new_entry = NULL; |
581 create_class_path_entry((char *)path, st, &new_entry, LazyBootClassLoader); |
589 Thread* THREAD = Thread::current(); |
|
590 new_entry = create_class_path_entry(path, &st, LazyBootClassLoader, CHECK); |
582 // The kernel VM adds dynamically to the end of the classloader path and |
591 // The kernel VM adds dynamically to the end of the classloader path and |
583 // doesn't reorder the bootclasspath which would break java.lang.Package |
592 // doesn't reorder the bootclasspath which would break java.lang.Package |
584 // (see PackageInfo). |
593 // (see PackageInfo). |
585 // Add new entry to linked list |
594 // Add new entry to linked list |
586 if (!check_for_duplicates || !contains_entry(new_entry)) { |
595 if (!check_for_duplicates || !contains_entry(new_entry)) { |
895 PerfClassTraceTime vmtimer(perf_sys_class_lookup_time(), |
904 PerfClassTraceTime vmtimer(perf_sys_class_lookup_time(), |
896 ((JavaThread*) THREAD)->get_thread_stat()->perf_timers_addr(), |
905 ((JavaThread*) THREAD)->get_thread_stat()->perf_timers_addr(), |
897 PerfClassTraceTime::CLASS_LOAD); |
906 PerfClassTraceTime::CLASS_LOAD); |
898 ClassPathEntry* e = _first_entry; |
907 ClassPathEntry* e = _first_entry; |
899 while (e != NULL) { |
908 while (e != NULL) { |
900 stream = e->open_stream(name); |
909 stream = e->open_stream(name, CHECK_NULL); |
901 if (stream != NULL) { |
910 if (stream != NULL) { |
902 break; |
911 break; |
903 } |
912 } |
904 e = e->next(); |
913 e = e->next(); |
905 ++classpath_index; |
914 ++classpath_index; |
1255 // only used for debugging. |
1264 // only used for debugging. |
1256 return (len >= 6) && (strcasecmp(zip->name + len - 6, "rt.jar") == 0); |
1265 return (len >= 6) && (strcasecmp(zip->name + len - 6, "rt.jar") == 0); |
1257 } |
1266 } |
1258 |
1267 |
1259 void LazyClassPathEntry::compile_the_world(Handle loader, TRAPS) { |
1268 void LazyClassPathEntry::compile_the_world(Handle loader, TRAPS) { |
1260 resolve_entry()->compile_the_world(loader, CHECK); |
1269 ClassPathEntry* cpe = resolve_entry(THREAD); |
|
1270 if (cpe != NULL) { |
|
1271 cpe->compile_the_world(loader, CHECK); |
|
1272 } |
1261 } |
1273 } |
1262 |
1274 |
1263 bool LazyClassPathEntry::is_rt_jar() { |
1275 bool LazyClassPathEntry::is_rt_jar() { |
1264 return resolve_entry()->is_rt_jar(); |
1276 Thread* THREAD = Thread::current(); |
|
1277 ClassPathEntry* cpe = resolve_entry(THREAD); |
|
1278 return (cpe != NULL) ? cpe->is_jar_file() : false; |
1265 } |
1279 } |
1266 |
1280 |
1267 void ClassLoader::compile_the_world() { |
1281 void ClassLoader::compile_the_world() { |
1268 EXCEPTION_MARK; |
1282 EXCEPTION_MARK; |
1269 HandleMark hm(THREAD); |
1283 HandleMark hm(THREAD); |