51 #include "runtime/fprofiler.hpp"
52 #include "runtime/handles.hpp"
53 #include "runtime/handles.inline.hpp"
54 #include "runtime/init.hpp"
55 #include "runtime/interfaceSupport.hpp"
56 #include "runtime/java.hpp"
57 #include "runtime/javaCalls.hpp"
58 #include "runtime/os.hpp"
59 #include "runtime/threadCritical.hpp"
60 #include "runtime/timer.hpp"
61 #include "services/management.hpp"
62 #include "services/threadService.hpp"
63 #include "utilities/events.hpp"
64 #include "utilities/hashtable.inline.hpp"
65 #include "utilities/macros.hpp"
66 #if INCLUDE_CDS
67 #include "classfile/sharedClassUtil.hpp"
68 #include "classfile/sharedPathsMiscInfo.hpp"
69 #endif
70
71
72 // Entry points in zip.dll for loading zip/jar file entries and image file entries
73
74 typedef void * * (JNICALL *ZipOpen_t)(const char *name, char **pmsg);
75 typedef void (JNICALL *ZipClose_t)(jzfile *zip);
76 typedef jzentry* (JNICALL *FindEntry_t)(jzfile *zip, const char *name, jint *sizeP, jint *nameLen);
77 typedef jboolean (JNICALL *ReadEntry_t)(jzfile *zip, jzentry *entry, unsigned char *buf, char *namebuf);
78 typedef jboolean (JNICALL *ReadMappedEntry_t)(jzfile *zip, jzentry *entry, unsigned char **buf, char *namebuf);
79 typedef jzentry* (JNICALL *GetNextEntry_t)(jzfile *zip, jint n);
80 typedef jboolean (JNICALL *ZipInflateFully_t)(void *inBuf, jlong inLen, void *outBuf, jlong outLen, char **pmsg);
81 typedef jint (JNICALL *Crc32_t)(jint crc, const jbyte *buf, jint len);
82
83 static ZipOpen_t ZipOpen = NULL;
84 static ZipClose_t ZipClose = NULL;
85 static FindEntry_t FindEntry = NULL;
86 static ReadEntry_t ReadEntry = NULL;
87 static ReadMappedEntry_t ReadMappedEntry = NULL;
88 static GetNextEntry_t GetNextEntry = NULL;
89 static canonicalize_fn_t CanonicalizeEntry = NULL;
90 static ZipInflateFully_t ZipInflateFully = NULL;
91 static Crc32_t Crc32 = NULL;
150 }
151 return (strncmp(str + (str_len - str_to_find_len), str_to_find, str_to_find_len) == 0);
152 }
153
154
155 ClassPathEntry::ClassPathEntry() {
156 set_next(NULL);
157 }
158
159
160 bool ClassPathEntry::is_lazy() {
161 return false;
162 }
163
164 ClassPathDirEntry::ClassPathDirEntry(const char* dir) : ClassPathEntry() {
165 char* copy = NEW_C_HEAP_ARRAY(char, strlen(dir)+1, mtClass);
166 strcpy(copy, dir);
167 _dir = copy;
168 }
169
170
171 ClassFileStream* ClassPathDirEntry::open_stream(const char* name, TRAPS) {
172 // construct full path name
173 char path[JVM_MAXPATHLEN];
174 if (jio_snprintf(path, sizeof(path), "%s%s%s", _dir, os::file_separator(), name) == -1) {
175 return NULL;
176 }
177 // check if file exists
178 struct stat st;
179 if (os::stat(path, &st) == 0) {
180 #if INCLUDE_CDS
181 if (DumpSharedSpaces) {
182 // We have already check in ClassLoader::check_shared_classpath() that the directory is empty, so
183 // we should never find a file underneath it -- unless user has added a new file while we are running
184 // the dump, in which case let's quit!
185 ShouldNotReachHere();
186 }
187 #endif
188 // found file, open it
189 int file_handle = os::open(path, 0, 0);
190 if (file_handle != -1) {
335 return true;
336 }
337
338 u1* LazyClassPathEntry::open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS) {
339 if (_has_error) {
340 return NULL;
341 }
342 ClassPathEntry* cpe = resolve_entry(THREAD);
343 if (cpe == NULL) {
344 _has_error = true;
345 return NULL;
346 } else if (cpe->is_jar_file()) {
347 return ((ClassPathZipEntry*)cpe)->open_entry(name, filesize, nul_terminate,THREAD);
348 } else {
349 ShouldNotReachHere();
350 *filesize = 0;
351 return NULL;
352 }
353 }
354
355 ClassPathImageEntry::ClassPathImageEntry(char* name) : ClassPathEntry(), _image(new ImageFile(name)) {
356 bool opened = _image->open();
357 if (!opened) {
358 _image = NULL;
359 }
360 }
361
362 ClassPathImageEntry::~ClassPathImageEntry() {
363 if (_image) {
364 _image->close();
365 _image = NULL;
366 }
367 }
368
369 const char* ClassPathImageEntry::name() {
370 return _image ? _image->name() : "";
371 }
372
373 ClassFileStream* ClassPathImageEntry::open_stream(const char* name, TRAPS) {
374 u1* buffer;
375 u8 size;
376 _image->get_resource(name, buffer, size);
377
378 if (buffer) {
379 if (UsePerfData) {
380 ClassLoader::perf_sys_classfile_bytes_read()->inc(size);
381 }
382 return new ClassFileStream(buffer, (int)size, (char*)name); // Resource allocated
383 }
384
385 return NULL;
386 }
387
388 #ifndef PRODUCT
389 void ClassPathImageEntry::compile_the_world(Handle loader, TRAPS) {
390 tty->print_cr("CompileTheWorld : Compiling all classes in %s", name());
391 tty->cr();
392 const ImageStrings strings = _image->get_strings();
393 // Retrieve each path component string.
394 u4 count = _image->get_location_count();
395 for (u4 i = 0; i < count; i++) {
396 u1* location_data = _image->get_location_data(i);
397
398 if (location_data) {
399 ImageLocation location(location_data);
400 const char* parent = location.get_attribute(ImageLocation::ATTRIBUTE_PARENT, strings);
401 const char* base = location.get_attribute(ImageLocation::ATTRIBUTE_BASE, strings);
402 const char* extension = location.get_attribute(ImageLocation::ATTRIBUTE_EXTENSION, strings);
403 assert((strlen(parent) + strlen(base) + strlen(extension)) < JVM_MAXPATHLEN, "path exceeds buffer");
404 char path[JVM_MAXPATHLEN];
405 strcpy(path, parent);
406 strcat(path, base);
407 strcat(path, extension);
408 ClassLoader::compile_the_world_in(path, loader, CHECK);
409 }
410 }
411 if (HAS_PENDING_EXCEPTION) {
412 if (PENDING_EXCEPTION->is_a(SystemDictionary::OutOfMemoryError_klass())) {
413 CLEAR_PENDING_EXCEPTION;
414 tty->print_cr("\nCompileTheWorld : Ran out of memory\n");
415 tty->print_cr("Increase class metadata storage if a limit was set");
416 } else {
417 tty->print_cr("\nCompileTheWorld : Unexpected exception occurred\n");
418 }
419 }
420 }
421
422 bool ClassPathImageEntry::is_jrt() {
423 return string_ends_with(name(), "bootmodules.jimage");
424 }
425 #endif
426
427 #if INCLUDE_CDS
428 void ClassLoader::exit_with_path_failure(const char* error, const char* message) {
429 assert(DumpSharedSpaces, "only called at dump time");
430 tty->print_cr("Hint: enable -XX:+TraceClassPaths to diagnose the failure");
431 vm_exit_during_initialization(error, message);
432 }
433 #endif
434
435 void ClassLoader::trace_class_path(const char* msg, const char* name) {
436 if (!TraceClassPaths) {
437 return;
438 }
439
440 if (msg) {
441 tty->print("%s", msg);
442 }
443 if (name) {
540
541 ClassPathEntry* ClassLoader::create_class_path_entry(const char *path, const struct stat* st,
542 bool lazy, bool throw_exception, TRAPS) {
543 JavaThread* thread = JavaThread::current();
544 if (lazy) {
545 return new LazyClassPathEntry(path, st, throw_exception);
546 }
547 ClassPathEntry* new_entry = NULL;
548 if ((st->st_mode & S_IFREG) == S_IFREG) {
549 // Regular file, should be a zip or image file
550 // Canonicalized filename
551 char canonical_path[JVM_MAXPATHLEN];
552 if (!get_canonical_path(path, canonical_path, JVM_MAXPATHLEN)) {
553 // This matches the classic VM
554 if (throw_exception) {
555 THROW_MSG_(vmSymbols::java_io_IOException(), "Bad pathname", NULL);
556 } else {
557 return NULL;
558 }
559 }
560 // TODO - add proper criteria for selecting image file
561 ClassPathImageEntry* entry = new ClassPathImageEntry(canonical_path);
562 if (entry->is_open()) {
563 new_entry = entry;
564 } else {
565 char* error_msg = NULL;
566 jzfile* zip;
567 {
568 // enable call to C land
569 ThreadToNativeFromVM ttn(thread);
570 HandleMark hm(thread);
571 zip = (*ZipOpen)(canonical_path, &error_msg);
572 }
573 if (zip != NULL && error_msg == NULL) {
574 new_entry = new ClassPathZipEntry(zip, path);
575 } else {
576 ResourceMark rm(thread);
577 char *msg;
578 if (error_msg == NULL) {
579 msg = NEW_RESOURCE_ARRAY(char, strlen(path) + 128); ;
580 jio_snprintf(msg, strlen(path) + 127, "error in opening JAR file %s", path);
581 } else {
582 int len = (int)(strlen(path) + strlen(error_msg) + 128);
583 msg = NEW_RESOURCE_ARRAY(char, len); ;
|
51 #include "runtime/fprofiler.hpp"
52 #include "runtime/handles.hpp"
53 #include "runtime/handles.inline.hpp"
54 #include "runtime/init.hpp"
55 #include "runtime/interfaceSupport.hpp"
56 #include "runtime/java.hpp"
57 #include "runtime/javaCalls.hpp"
58 #include "runtime/os.hpp"
59 #include "runtime/threadCritical.hpp"
60 #include "runtime/timer.hpp"
61 #include "services/management.hpp"
62 #include "services/threadService.hpp"
63 #include "utilities/events.hpp"
64 #include "utilities/hashtable.inline.hpp"
65 #include "utilities/macros.hpp"
66 #if INCLUDE_CDS
67 #include "classfile/sharedClassUtil.hpp"
68 #include "classfile/sharedPathsMiscInfo.hpp"
69 #endif
70
71 // Entry points in zip.dll for loading zip/jar file entries and image file entries
72
73 typedef void * * (JNICALL *ZipOpen_t)(const char *name, char **pmsg);
74 typedef void (JNICALL *ZipClose_t)(jzfile *zip);
75 typedef jzentry* (JNICALL *FindEntry_t)(jzfile *zip, const char *name, jint *sizeP, jint *nameLen);
76 typedef jboolean (JNICALL *ReadEntry_t)(jzfile *zip, jzentry *entry, unsigned char *buf, char *namebuf);
77 typedef jboolean (JNICALL *ReadMappedEntry_t)(jzfile *zip, jzentry *entry, unsigned char **buf, char *namebuf);
78 typedef jzentry* (JNICALL *GetNextEntry_t)(jzfile *zip, jint n);
79 typedef jboolean (JNICALL *ZipInflateFully_t)(void *inBuf, jlong inLen, void *outBuf, jlong outLen, char **pmsg);
80 typedef jint (JNICALL *Crc32_t)(jint crc, const jbyte *buf, jint len);
81
82 static ZipOpen_t ZipOpen = NULL;
83 static ZipClose_t ZipClose = NULL;
84 static FindEntry_t FindEntry = NULL;
85 static ReadEntry_t ReadEntry = NULL;
86 static ReadMappedEntry_t ReadMappedEntry = NULL;
87 static GetNextEntry_t GetNextEntry = NULL;
88 static canonicalize_fn_t CanonicalizeEntry = NULL;
89 static ZipInflateFully_t ZipInflateFully = NULL;
90 static Crc32_t Crc32 = NULL;
149 }
150 return (strncmp(str + (str_len - str_to_find_len), str_to_find, str_to_find_len) == 0);
151 }
152
153
154 ClassPathEntry::ClassPathEntry() {
155 set_next(NULL);
156 }
157
158
159 bool ClassPathEntry::is_lazy() {
160 return false;
161 }
162
163 ClassPathDirEntry::ClassPathDirEntry(const char* dir) : ClassPathEntry() {
164 char* copy = NEW_C_HEAP_ARRAY(char, strlen(dir)+1, mtClass);
165 strcpy(copy, dir);
166 _dir = copy;
167 }
168
169 ClassFileStream* ClassPathDirEntry::open_stream(const char* name, TRAPS) {
170 // construct full path name
171 char path[JVM_MAXPATHLEN];
172 if (jio_snprintf(path, sizeof(path), "%s%s%s", _dir, os::file_separator(), name) == -1) {
173 return NULL;
174 }
175 // check if file exists
176 struct stat st;
177 if (os::stat(path, &st) == 0) {
178 #if INCLUDE_CDS
179 if (DumpSharedSpaces) {
180 // We have already check in ClassLoader::check_shared_classpath() that the directory is empty, so
181 // we should never find a file underneath it -- unless user has added a new file while we are running
182 // the dump, in which case let's quit!
183 ShouldNotReachHere();
184 }
185 #endif
186 // found file, open it
187 int file_handle = os::open(path, 0, 0);
188 if (file_handle != -1) {
333 return true;
334 }
335
336 u1* LazyClassPathEntry::open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS) {
337 if (_has_error) {
338 return NULL;
339 }
340 ClassPathEntry* cpe = resolve_entry(THREAD);
341 if (cpe == NULL) {
342 _has_error = true;
343 return NULL;
344 } else if (cpe->is_jar_file()) {
345 return ((ClassPathZipEntry*)cpe)->open_entry(name, filesize, nul_terminate,THREAD);
346 } else {
347 ShouldNotReachHere();
348 *filesize = 0;
349 return NULL;
350 }
351 }
352
353 ClassPathImageEntry::ClassPathImageEntry(ImageFileReader* image) :
354 ClassPathEntry(),
355 _image(image),
356 _module_data(NULL) {
357 guarantee(image != NULL, "image file is null");
358
359 char module_data_name[JVM_MAXPATHLEN];
360 ImageModuleData::module_data_name(module_data_name, _image->name());
361 _module_data = new ImageModuleData(_image, module_data_name);
362 }
363
364 ClassPathImageEntry::~ClassPathImageEntry() {
365 if (_module_data != NULL) {
366 delete _module_data;
367 _module_data = NULL;
368 }
369
370 if (_image != NULL) {
371 ImageFileReader::close(_image);
372 _image = NULL;
373 }
374 }
375
376 const char* ClassPathImageEntry::name() {
377 return _image ? _image->name() : "";
378 }
379
380 ClassFileStream* ClassPathImageEntry::open_stream(const char* name, TRAPS) {
381 ImageLocation location;
382 bool found = _image->find_location(name, location);
383
384 if (!found) {
385 const char *pslash = strrchr(name, '/');
386 int len = pslash - name;
387
388 // NOTE: IMAGE_MAX_PATH is used here since this path is internal to the jimage
389 // (effectively unlimited.) There are several JCK tests that use paths over
390 // 1024 characters long, the limit on Windows systems.
391 if (pslash && 0 < len && len < IMAGE_MAX_PATH) {
392
393 char path[IMAGE_MAX_PATH];
394 strncpy(path, name, len);
395 path[len] = '\0';
396 const char* moduleName = _module_data->package_to_module(path);
397
398 if (moduleName != NULL && (len + strlen(moduleName) + 2) < IMAGE_MAX_PATH) {
399 jio_snprintf(path, IMAGE_MAX_PATH - 1, "/%s/%s", moduleName, name);
400 location.clear_data();
401 found = _image->find_location(path, location);
402 }
403 }
404 }
405
406 if (found) {
407 u8 size = location.get_attribute(ImageLocation::ATTRIBUTE_UNCOMPRESSED);
408 if (UsePerfData) {
409 ClassLoader::perf_sys_classfile_bytes_read()->inc(size);
410 }
411 u1* data = NEW_RESOURCE_ARRAY(u1, size);
412 _image->get_resource(location, data);
413 return new ClassFileStream(data, (int)size, _image->name()); // Resource allocated
414 }
415
416 return NULL;
417 }
418
419 #ifndef PRODUCT
420 void ClassPathImageEntry::compile_the_world(Handle loader, TRAPS) {
421 tty->print_cr("CompileTheWorld : Compiling all classes in %s", name());
422 tty->cr();
423 const ImageStrings strings = _image->get_strings();
424 // Retrieve each path component string.
425 u4 length = _image->table_length();
426 for (u4 i = 0; i < length; i++) {
427 u1* location_data = _image->get_location_data(i);
428
429 if (location_data != NULL) {
430 ImageLocation location(location_data);
431 char path[IMAGE_MAX_PATH];
432 _image->location_path(location, path, IMAGE_MAX_PATH);
433 ClassLoader::compile_the_world_in(path, loader, CHECK);
434 }
435 }
436 if (HAS_PENDING_EXCEPTION) {
437 if (PENDING_EXCEPTION->is_a(SystemDictionary::OutOfMemoryError_klass())) {
438 CLEAR_PENDING_EXCEPTION;
439 tty->print_cr("\nCompileTheWorld : Ran out of memory\n");
440 tty->print_cr("Increase class metadata storage if a limit was set");
441 } else {
442 tty->print_cr("\nCompileTheWorld : Unexpected exception occurred\n");
443 }
444 }
445 }
446
447 bool ClassPathImageEntry::is_jrt() {
448 return string_ends_with(name(), BOOT_IMAGE_NAME);
449 }
450 #endif
451
452 #if INCLUDE_CDS
453 void ClassLoader::exit_with_path_failure(const char* error, const char* message) {
454 assert(DumpSharedSpaces, "only called at dump time");
455 tty->print_cr("Hint: enable -XX:+TraceClassPaths to diagnose the failure");
456 vm_exit_during_initialization(error, message);
457 }
458 #endif
459
460 void ClassLoader::trace_class_path(const char* msg, const char* name) {
461 if (!TraceClassPaths) {
462 return;
463 }
464
465 if (msg) {
466 tty->print("%s", msg);
467 }
468 if (name) {
565
566 ClassPathEntry* ClassLoader::create_class_path_entry(const char *path, const struct stat* st,
567 bool lazy, bool throw_exception, TRAPS) {
568 JavaThread* thread = JavaThread::current();
569 if (lazy) {
570 return new LazyClassPathEntry(path, st, throw_exception);
571 }
572 ClassPathEntry* new_entry = NULL;
573 if ((st->st_mode & S_IFREG) == S_IFREG) {
574 // Regular file, should be a zip or image file
575 // Canonicalized filename
576 char canonical_path[JVM_MAXPATHLEN];
577 if (!get_canonical_path(path, canonical_path, JVM_MAXPATHLEN)) {
578 // This matches the classic VM
579 if (throw_exception) {
580 THROW_MSG_(vmSymbols::java_io_IOException(), "Bad pathname", NULL);
581 } else {
582 return NULL;
583 }
584 }
585 ImageFileReader* image = ImageFileReader::open(canonical_path);
586 if (image != NULL) {
587 new_entry = new ClassPathImageEntry(image);
588 } else {
589 char* error_msg = NULL;
590 jzfile* zip;
591 {
592 // enable call to C land
593 ThreadToNativeFromVM ttn(thread);
594 HandleMark hm(thread);
595 zip = (*ZipOpen)(canonical_path, &error_msg);
596 }
597 if (zip != NULL && error_msg == NULL) {
598 new_entry = new ClassPathZipEntry(zip, path);
599 } else {
600 ResourceMark rm(thread);
601 char *msg;
602 if (error_msg == NULL) {
603 msg = NEW_RESOURCE_ARRAY(char, strlen(path) + 128); ;
604 jio_snprintf(msg, strlen(path) + 127, "error in opening JAR file %s", path);
605 } else {
606 int len = (int)(strlen(path) + strlen(error_msg) + 128);
607 msg = NEW_RESOURCE_ARRAY(char, len); ;
|