Mercurial > hg > truffle
comparison src/share/vm/classfile/classLoader.cpp @ 12135:7e7dd25666da
8020675: invalid jar file in the bootclasspath could lead to jvm fatal error
Summary: removed offending EXCEPTION_MARK calls and code cleanup
Reviewed-by: dholmes, iklam, coleenp, mseledtsov
author | ccheung |
---|---|
date | Mon, 26 Aug 2013 14:11:26 -0700 |
parents | 6e04c193845f |
children | 3a4e6c929bf3 |
comparison
equal
deleted
inserted
replaced
12111:21ffbaa691b5 | 12135:7e7dd25666da |
---|---|
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); |