Merge
This commit is contained in:
commit
88ff99b454
@ -141,6 +141,18 @@ SUNWprivate_1.1 {
|
|||||||
JVM_Halt;
|
JVM_Halt;
|
||||||
JVM_HoldsLock;
|
JVM_HoldsLock;
|
||||||
JVM_IHashCode;
|
JVM_IHashCode;
|
||||||
|
JVM_ImageAttributeOffsets;
|
||||||
|
JVM_ImageAttributeOffsetsLength;
|
||||||
|
JVM_ImageClose;
|
||||||
|
JVM_ImageFindAttributes;
|
||||||
|
JVM_ImageGetAttributes;
|
||||||
|
JVM_ImageGetAttributesCount;
|
||||||
|
JVM_ImageGetDataAddress;
|
||||||
|
JVM_ImageGetIndexAddress;
|
||||||
|
JVM_ImageGetStringBytes;
|
||||||
|
JVM_ImageOpen;
|
||||||
|
JVM_ImageRead;
|
||||||
|
JVM_ImageReadCompressed;
|
||||||
JVM_InitAgentProperties;
|
JVM_InitAgentProperties;
|
||||||
JVM_InitProperties;
|
JVM_InitProperties;
|
||||||
JVM_InternString;
|
JVM_InternString;
|
||||||
|
@ -139,6 +139,18 @@ SUNWprivate_1.1 {
|
|||||||
JVM_Halt;
|
JVM_Halt;
|
||||||
JVM_HoldsLock;
|
JVM_HoldsLock;
|
||||||
JVM_IHashCode;
|
JVM_IHashCode;
|
||||||
|
JVM_ImageAttributeOffsets;
|
||||||
|
JVM_ImageAttributeOffsetsLength;
|
||||||
|
JVM_ImageClose;
|
||||||
|
JVM_ImageFindAttributes;
|
||||||
|
JVM_ImageGetAttributes;
|
||||||
|
JVM_ImageGetAttributesCount;
|
||||||
|
JVM_ImageGetDataAddress;
|
||||||
|
JVM_ImageGetIndexAddress;
|
||||||
|
JVM_ImageGetStringBytes;
|
||||||
|
JVM_ImageOpen;
|
||||||
|
JVM_ImageRead;
|
||||||
|
JVM_ImageReadCompressed;
|
||||||
JVM_InitAgentProperties;
|
JVM_InitAgentProperties;
|
||||||
JVM_InitProperties;
|
JVM_InitProperties;
|
||||||
JVM_InternString;
|
JVM_InternString;
|
||||||
|
@ -139,6 +139,18 @@
|
|||||||
_JVM_Halt
|
_JVM_Halt
|
||||||
_JVM_HoldsLock
|
_JVM_HoldsLock
|
||||||
_JVM_IHashCode
|
_JVM_IHashCode
|
||||||
|
_JVM_ImageAttributeOffsets
|
||||||
|
_JVM_ImageAttributeOffsetsLength
|
||||||
|
_JVM_ImageClose
|
||||||
|
_JVM_ImageFindAttributes
|
||||||
|
_JVM_ImageGetAttributes
|
||||||
|
_JVM_ImageGetAttributesCount
|
||||||
|
_JVM_ImageGetDataAddress
|
||||||
|
_JVM_ImageGetIndexAddress
|
||||||
|
_JVM_ImageGetStringBytes
|
||||||
|
_JVM_ImageOpen
|
||||||
|
_JVM_ImageRead
|
||||||
|
_JVM_ImageReadCompressed
|
||||||
_JVM_InitAgentProperties
|
_JVM_InitAgentProperties
|
||||||
_JVM_InitProperties
|
_JVM_InitProperties
|
||||||
_JVM_InternString
|
_JVM_InternString
|
||||||
@ -188,7 +200,7 @@
|
|||||||
_JVM_Yield
|
_JVM_Yield
|
||||||
_JVM_handle_bsd_signal
|
_JVM_handle_bsd_signal
|
||||||
|
|
||||||
# miscellaneous functions
|
# miscellaneous functions
|
||||||
_jio_fprintf
|
_jio_fprintf
|
||||||
_jio_printf
|
_jio_printf
|
||||||
_jio_snprintf
|
_jio_snprintf
|
||||||
|
@ -139,6 +139,18 @@
|
|||||||
_JVM_Halt
|
_JVM_Halt
|
||||||
_JVM_HoldsLock
|
_JVM_HoldsLock
|
||||||
_JVM_IHashCode
|
_JVM_IHashCode
|
||||||
|
_JVM_ImageAttributeOffsets
|
||||||
|
_JVM_ImageAttributeOffsetsLength
|
||||||
|
_JVM_ImageClose
|
||||||
|
_JVM_ImageFindAttributes
|
||||||
|
_JVM_ImageGetAttributes
|
||||||
|
_JVM_ImageGetAttributesCount
|
||||||
|
_JVM_ImageGetDataAddress
|
||||||
|
_JVM_ImageGetIndexAddress
|
||||||
|
_JVM_ImageGetStringBytes
|
||||||
|
_JVM_ImageOpen
|
||||||
|
_JVM_ImageRead
|
||||||
|
_JVM_ImageReadCompressed
|
||||||
_JVM_InitAgentProperties
|
_JVM_InitAgentProperties
|
||||||
_JVM_InitProperties
|
_JVM_InitProperties
|
||||||
_JVM_InternString
|
_JVM_InternString
|
||||||
|
@ -141,6 +141,18 @@ SUNWprivate_1.1 {
|
|||||||
JVM_Halt;
|
JVM_Halt;
|
||||||
JVM_HoldsLock;
|
JVM_HoldsLock;
|
||||||
JVM_IHashCode;
|
JVM_IHashCode;
|
||||||
|
JVM_ImageAttributeOffsets;
|
||||||
|
JVM_ImageAttributeOffsetsLength;
|
||||||
|
JVM_ImageClose;
|
||||||
|
JVM_ImageFindAttributes;
|
||||||
|
JVM_ImageGetAttributes;
|
||||||
|
JVM_ImageGetAttributesCount;
|
||||||
|
JVM_ImageGetDataAddress;
|
||||||
|
JVM_ImageGetIndexAddress;
|
||||||
|
JVM_ImageGetStringBytes;
|
||||||
|
JVM_ImageOpen;
|
||||||
|
JVM_ImageRead;
|
||||||
|
JVM_ImageReadCompressed;
|
||||||
JVM_InitAgentProperties;
|
JVM_InitAgentProperties;
|
||||||
JVM_InitProperties;
|
JVM_InitProperties;
|
||||||
JVM_InternString;
|
JVM_InternString;
|
||||||
|
@ -141,6 +141,18 @@ SUNWprivate_1.1 {
|
|||||||
JVM_Halt;
|
JVM_Halt;
|
||||||
JVM_HoldsLock;
|
JVM_HoldsLock;
|
||||||
JVM_IHashCode;
|
JVM_IHashCode;
|
||||||
|
JVM_ImageAttributeOffsets;
|
||||||
|
JVM_ImageAttributeOffsetsLength;
|
||||||
|
JVM_ImageClose;
|
||||||
|
JVM_ImageFindAttributes;
|
||||||
|
JVM_ImageGetAttributes;
|
||||||
|
JVM_ImageGetAttributesCount;
|
||||||
|
JVM_ImageGetDataAddress;
|
||||||
|
JVM_ImageGetIndexAddress;
|
||||||
|
JVM_ImageGetStringBytes;
|
||||||
|
JVM_ImageOpen;
|
||||||
|
JVM_ImageRead;
|
||||||
|
JVM_ImageReadCompressed;
|
||||||
JVM_InitAgentProperties;
|
JVM_InitAgentProperties;
|
||||||
JVM_InitProperties;
|
JVM_InitProperties;
|
||||||
JVM_InternString;
|
JVM_InternString;
|
||||||
|
@ -141,6 +141,18 @@ SUNWprivate_1.1 {
|
|||||||
JVM_Halt;
|
JVM_Halt;
|
||||||
JVM_HoldsLock;
|
JVM_HoldsLock;
|
||||||
JVM_IHashCode;
|
JVM_IHashCode;
|
||||||
|
JVM_ImageAttributeOffsets;
|
||||||
|
JVM_ImageAttributeOffsetsLength;
|
||||||
|
JVM_ImageClose;
|
||||||
|
JVM_ImageFindAttributes;
|
||||||
|
JVM_ImageGetAttributes;
|
||||||
|
JVM_ImageGetAttributesCount;
|
||||||
|
JVM_ImageGetDataAddress;
|
||||||
|
JVM_ImageGetIndexAddress;
|
||||||
|
JVM_ImageGetStringBytes;
|
||||||
|
JVM_ImageOpen;
|
||||||
|
JVM_ImageRead;
|
||||||
|
JVM_ImageReadCompressed;
|
||||||
JVM_InitAgentProperties;
|
JVM_InitAgentProperties;
|
||||||
JVM_InitProperties;
|
JVM_InitProperties;
|
||||||
JVM_InternString;
|
JVM_InternString;
|
||||||
|
@ -141,6 +141,18 @@ SUNWprivate_1.1 {
|
|||||||
JVM_Halt;
|
JVM_Halt;
|
||||||
JVM_HoldsLock;
|
JVM_HoldsLock;
|
||||||
JVM_IHashCode;
|
JVM_IHashCode;
|
||||||
|
JVM_ImageAttributeOffsets;
|
||||||
|
JVM_ImageAttributeOffsetsLength;
|
||||||
|
JVM_ImageClose;
|
||||||
|
JVM_ImageFindAttributes;
|
||||||
|
JVM_ImageGetAttributes;
|
||||||
|
JVM_ImageGetAttributesCount;
|
||||||
|
JVM_ImageGetDataAddress;
|
||||||
|
JVM_ImageGetIndexAddress;
|
||||||
|
JVM_ImageGetStringBytes;
|
||||||
|
JVM_ImageOpen;
|
||||||
|
JVM_ImageRead;
|
||||||
|
JVM_ImageReadCompressed;
|
||||||
JVM_InitAgentProperties;
|
JVM_InitAgentProperties;
|
||||||
JVM_InitProperties;
|
JVM_InitProperties;
|
||||||
JVM_InternString;
|
JVM_InternString;
|
||||||
|
@ -141,6 +141,18 @@ SUNWprivate_1.1 {
|
|||||||
JVM_Halt;
|
JVM_Halt;
|
||||||
JVM_HoldsLock;
|
JVM_HoldsLock;
|
||||||
JVM_IHashCode;
|
JVM_IHashCode;
|
||||||
|
JVM_ImageAttributeOffsets;
|
||||||
|
JVM_ImageAttributeOffsetsLength;
|
||||||
|
JVM_ImageClose;
|
||||||
|
JVM_ImageFindAttributes;
|
||||||
|
JVM_ImageGetAttributes;
|
||||||
|
JVM_ImageGetAttributesCount;
|
||||||
|
JVM_ImageGetDataAddress;
|
||||||
|
JVM_ImageGetIndexAddress;
|
||||||
|
JVM_ImageGetStringBytes;
|
||||||
|
JVM_ImageOpen;
|
||||||
|
JVM_ImageRead;
|
||||||
|
JVM_ImageReadCompressed;
|
||||||
JVM_InitAgentProperties;
|
JVM_InitAgentProperties;
|
||||||
JVM_InitProperties;
|
JVM_InitProperties;
|
||||||
JVM_InternString;
|
JVM_InternString;
|
||||||
|
@ -68,7 +68,6 @@
|
|||||||
#include "classfile/sharedPathsMiscInfo.hpp"
|
#include "classfile/sharedPathsMiscInfo.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// Entry points in zip.dll for loading zip/jar file entries and image file entries
|
// Entry points in zip.dll for loading zip/jar file entries and image file entries
|
||||||
|
|
||||||
typedef void * * (JNICALL *ZipOpen_t)(const char *name, char **pmsg);
|
typedef void * * (JNICALL *ZipOpen_t)(const char *name, char **pmsg);
|
||||||
@ -167,7 +166,6 @@ ClassPathDirEntry::ClassPathDirEntry(const char* dir) : ClassPathEntry() {
|
|||||||
_dir = copy;
|
_dir = copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ClassFileStream* ClassPathDirEntry::open_stream(const char* name, TRAPS) {
|
ClassFileStream* ClassPathDirEntry::open_stream(const char* name, TRAPS) {
|
||||||
// construct full path name
|
// construct full path name
|
||||||
char path[JVM_MAXPATHLEN];
|
char path[JVM_MAXPATHLEN];
|
||||||
@ -352,16 +350,25 @@ u1* LazyClassPathEntry::open_entry(const char* name, jint* filesize, bool nul_te
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ClassPathImageEntry::ClassPathImageEntry(char* name) : ClassPathEntry(), _image(new ImageFile(name)) {
|
ClassPathImageEntry::ClassPathImageEntry(ImageFileReader* image) :
|
||||||
bool opened = _image->open();
|
ClassPathEntry(),
|
||||||
if (!opened) {
|
_image(image),
|
||||||
_image = NULL;
|
_module_data(NULL) {
|
||||||
}
|
guarantee(image != NULL, "image file is null");
|
||||||
|
|
||||||
|
char module_data_name[JVM_MAXPATHLEN];
|
||||||
|
ImageModuleData::module_data_name(module_data_name, _image->name());
|
||||||
|
_module_data = new ImageModuleData(_image, module_data_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
ClassPathImageEntry::~ClassPathImageEntry() {
|
ClassPathImageEntry::~ClassPathImageEntry() {
|
||||||
if (_image) {
|
if (_module_data != NULL) {
|
||||||
_image->close();
|
delete _module_data;
|
||||||
|
_module_data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_image != NULL) {
|
||||||
|
ImageFileReader::close(_image);
|
||||||
_image = NULL;
|
_image = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -371,15 +378,39 @@ const char* ClassPathImageEntry::name() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ClassFileStream* ClassPathImageEntry::open_stream(const char* name, TRAPS) {
|
ClassFileStream* ClassPathImageEntry::open_stream(const char* name, TRAPS) {
|
||||||
u1* buffer;
|
ImageLocation location;
|
||||||
u8 size;
|
bool found = _image->find_location(name, location);
|
||||||
_image->get_resource(name, buffer, size);
|
|
||||||
|
|
||||||
if (buffer) {
|
if (!found) {
|
||||||
|
const char *pslash = strrchr(name, '/');
|
||||||
|
int len = pslash - name;
|
||||||
|
|
||||||
|
// NOTE: IMAGE_MAX_PATH is used here since this path is internal to the jimage
|
||||||
|
// (effectively unlimited.) There are several JCK tests that use paths over
|
||||||
|
// 1024 characters long, the limit on Windows systems.
|
||||||
|
if (pslash && 0 < len && len < IMAGE_MAX_PATH) {
|
||||||
|
|
||||||
|
char path[IMAGE_MAX_PATH];
|
||||||
|
strncpy(path, name, len);
|
||||||
|
path[len] = '\0';
|
||||||
|
const char* moduleName = _module_data->package_to_module(path);
|
||||||
|
|
||||||
|
if (moduleName != NULL && (len + strlen(moduleName) + 2) < IMAGE_MAX_PATH) {
|
||||||
|
jio_snprintf(path, IMAGE_MAX_PATH - 1, "/%s/%s", moduleName, name);
|
||||||
|
location.clear_data();
|
||||||
|
found = _image->find_location(path, location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found) {
|
||||||
|
u8 size = location.get_attribute(ImageLocation::ATTRIBUTE_UNCOMPRESSED);
|
||||||
if (UsePerfData) {
|
if (UsePerfData) {
|
||||||
ClassLoader::perf_sys_classfile_bytes_read()->inc(size);
|
ClassLoader::perf_sys_classfile_bytes_read()->inc(size);
|
||||||
}
|
}
|
||||||
return new ClassFileStream(buffer, (int)size, (char*)name); // Resource allocated
|
u1* data = NEW_RESOURCE_ARRAY(u1, size);
|
||||||
|
_image->get_resource(location, data);
|
||||||
|
return new ClassFileStream(data, (int)size, _image->name()); // Resource allocated
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -391,20 +422,14 @@ void ClassPathImageEntry::compile_the_world(Handle loader, TRAPS) {
|
|||||||
tty->cr();
|
tty->cr();
|
||||||
const ImageStrings strings = _image->get_strings();
|
const ImageStrings strings = _image->get_strings();
|
||||||
// Retrieve each path component string.
|
// Retrieve each path component string.
|
||||||
u4 count = _image->get_location_count();
|
u4 length = _image->table_length();
|
||||||
for (u4 i = 0; i < count; i++) {
|
for (u4 i = 0; i < length; i++) {
|
||||||
u1* location_data = _image->get_location_data(i);
|
u1* location_data = _image->get_location_data(i);
|
||||||
|
|
||||||
if (location_data) {
|
if (location_data != NULL) {
|
||||||
ImageLocation location(location_data);
|
ImageLocation location(location_data);
|
||||||
const char* parent = location.get_attribute(ImageLocation::ATTRIBUTE_PARENT, strings);
|
char path[IMAGE_MAX_PATH];
|
||||||
const char* base = location.get_attribute(ImageLocation::ATTRIBUTE_BASE, strings);
|
_image->location_path(location, path, IMAGE_MAX_PATH);
|
||||||
const char* extension = location.get_attribute(ImageLocation::ATTRIBUTE_EXTENSION, strings);
|
|
||||||
assert((strlen(parent) + strlen(base) + strlen(extension)) < JVM_MAXPATHLEN, "path exceeds buffer");
|
|
||||||
char path[JVM_MAXPATHLEN];
|
|
||||||
strcpy(path, parent);
|
|
||||||
strcat(path, base);
|
|
||||||
strcat(path, extension);
|
|
||||||
ClassLoader::compile_the_world_in(path, loader, CHECK);
|
ClassLoader::compile_the_world_in(path, loader, CHECK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -420,7 +445,7 @@ void ClassPathImageEntry::compile_the_world(Handle loader, TRAPS) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ClassPathImageEntry::is_jrt() {
|
bool ClassPathImageEntry::is_jrt() {
|
||||||
return string_ends_with(name(), "bootmodules.jimage");
|
return string_ends_with(name(), BOOT_IMAGE_NAME);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -557,10 +582,9 @@ ClassPathEntry* ClassLoader::create_class_path_entry(const char *path, const str
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO - add proper criteria for selecting image file
|
ImageFileReader* image = ImageFileReader::open(canonical_path);
|
||||||
ClassPathImageEntry* entry = new ClassPathImageEntry(canonical_path);
|
if (image != NULL) {
|
||||||
if (entry->is_open()) {
|
new_entry = new ClassPathImageEntry(image);
|
||||||
new_entry = entry;
|
|
||||||
} else {
|
} else {
|
||||||
char* error_msg = NULL;
|
char* error_msg = NULL;
|
||||||
jzfile* zip;
|
jzfile* zip;
|
||||||
|
@ -32,9 +32,14 @@
|
|||||||
// The VM class loader.
|
// The VM class loader.
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
// Name of boot module image
|
||||||
|
#define BOOT_IMAGE_NAME "bootmodules.jimage"
|
||||||
|
|
||||||
// Class path entry (directory or zip file)
|
// Class path entry (directory or zip file)
|
||||||
|
|
||||||
|
class ImageFileReader;
|
||||||
|
class ImageModuleData;
|
||||||
|
|
||||||
class ClassPathEntry: public CHeapObj<mtClass> {
|
class ClassPathEntry: public CHeapObj<mtClass> {
|
||||||
private:
|
private:
|
||||||
ClassPathEntry* _next;
|
ClassPathEntry* _next;
|
||||||
@ -47,6 +52,7 @@ class ClassPathEntry: public CHeapObj<mtClass> {
|
|||||||
}
|
}
|
||||||
virtual bool is_jar_file() = 0;
|
virtual bool is_jar_file() = 0;
|
||||||
virtual const char* name() = 0;
|
virtual const char* name() = 0;
|
||||||
|
virtual ImageFileReader* image() = 0;
|
||||||
virtual bool is_lazy();
|
virtual bool is_lazy();
|
||||||
// Constructor
|
// Constructor
|
||||||
ClassPathEntry();
|
ClassPathEntry();
|
||||||
@ -63,8 +69,9 @@ class ClassPathDirEntry: public ClassPathEntry {
|
|||||||
private:
|
private:
|
||||||
const char* _dir; // Name of directory
|
const char* _dir; // Name of directory
|
||||||
public:
|
public:
|
||||||
bool is_jar_file() { return false; }
|
bool is_jar_file() { return false; }
|
||||||
const char* name() { return _dir; }
|
const char* name() { return _dir; }
|
||||||
|
ImageFileReader* image() { return NULL; }
|
||||||
ClassPathDirEntry(const char* dir);
|
ClassPathDirEntry(const char* dir);
|
||||||
ClassFileStream* open_stream(const char* name, TRAPS);
|
ClassFileStream* open_stream(const char* name, TRAPS);
|
||||||
// Debugging
|
// Debugging
|
||||||
@ -92,8 +99,9 @@ class ClassPathZipEntry: public ClassPathEntry {
|
|||||||
jzfile* _zip; // The zip archive
|
jzfile* _zip; // The zip archive
|
||||||
const char* _zip_name; // Name of zip archive
|
const char* _zip_name; // Name of zip archive
|
||||||
public:
|
public:
|
||||||
bool is_jar_file() { return true; }
|
bool is_jar_file() { return true; }
|
||||||
const char* name() { return _zip_name; }
|
const char* name() { return _zip_name; }
|
||||||
|
ImageFileReader* image() { return NULL; }
|
||||||
ClassPathZipEntry(jzfile* zip, const char* zip_name);
|
ClassPathZipEntry(jzfile* zip, const char* zip_name);
|
||||||
~ClassPathZipEntry();
|
~ClassPathZipEntry();
|
||||||
u1* open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS);
|
u1* open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS);
|
||||||
@ -116,7 +124,8 @@ class LazyClassPathEntry: public ClassPathEntry {
|
|||||||
ClassPathEntry* resolve_entry(TRAPS);
|
ClassPathEntry* resolve_entry(TRAPS);
|
||||||
public:
|
public:
|
||||||
bool is_jar_file();
|
bool is_jar_file();
|
||||||
const char* name() { return _path; }
|
const char* name() { return _path; }
|
||||||
|
ImageFileReader* image() { return NULL; }
|
||||||
LazyClassPathEntry(const char* path, const struct stat* st, bool throw_exception);
|
LazyClassPathEntry(const char* path, const struct stat* st, bool throw_exception);
|
||||||
virtual ~LazyClassPathEntry();
|
virtual ~LazyClassPathEntry();
|
||||||
u1* open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS);
|
u1* open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS);
|
||||||
@ -129,15 +138,17 @@ class LazyClassPathEntry: public ClassPathEntry {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// For java image files
|
// For java image files
|
||||||
class ImageFile;
|
|
||||||
class ClassPathImageEntry: public ClassPathEntry {
|
class ClassPathImageEntry: public ClassPathEntry {
|
||||||
private:
|
private:
|
||||||
ImageFile *_image;
|
ImageFileReader* _image;
|
||||||
|
ImageModuleData* _module_data;
|
||||||
public:
|
public:
|
||||||
bool is_jar_file() { return false; }
|
bool is_jar_file() { return false; }
|
||||||
bool is_open() { return _image != NULL; }
|
bool is_open() { return _image != NULL; }
|
||||||
const char* name();
|
const char* name();
|
||||||
ClassPathImageEntry(char* name);
|
ImageFileReader* image() { return _image; }
|
||||||
|
ImageModuleData* module_data() { return _module_data; }
|
||||||
|
ClassPathImageEntry(ImageFileReader* image);
|
||||||
~ClassPathImageEntry();
|
~ClassPathImageEntry();
|
||||||
ClassFileStream* open_stream(const char* name, TRAPS);
|
ClassFileStream* open_stream(const char* name, TRAPS);
|
||||||
|
|
||||||
|
121
hotspot/src/share/vm/classfile/imageDecompressor.cpp
Normal file
121
hotspot/src/share/vm/classfile/imageDecompressor.cpp
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "runtime/thread.inline.hpp"
|
||||||
|
#include "precompiled.hpp"
|
||||||
|
#include "classfile/imageDecompressor.hpp"
|
||||||
|
#include "runtime/thread.hpp"
|
||||||
|
#include "utilities/bytes.hpp"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate in C Heap not in resource area, otherwise JVM crashes.
|
||||||
|
* This array life time is the VM life time. Array is never freed and
|
||||||
|
* is not expected to contain more than few references.
|
||||||
|
*/
|
||||||
|
GrowableArray<ImageDecompressor*>* ImageDecompressor::_decompressors =
|
||||||
|
new(ResourceObj::C_HEAP, mtInternal) GrowableArray<ImageDecompressor*>(2, true);
|
||||||
|
|
||||||
|
static Symbol* createSymbol(const char* str) {
|
||||||
|
Thread* THREAD = Thread::current();
|
||||||
|
Symbol* sym = SymbolTable::lookup(str, (int) strlen(str), THREAD);
|
||||||
|
if (HAS_PENDING_EXCEPTION) {
|
||||||
|
warning("can't create symbol\n");
|
||||||
|
CLEAR_PENDING_EXCEPTION;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return sym;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize the array of decompressors.
|
||||||
|
*/
|
||||||
|
bool image_decompressor_init() {
|
||||||
|
Symbol* zipSymbol = createSymbol("zip");
|
||||||
|
if (zipSymbol == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ImageDecompressor::add_decompressor(new ZipDecompressor(zipSymbol));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decompression entry point. Called from ImageFileReader::get_resource.
|
||||||
|
*/
|
||||||
|
void ImageDecompressor::decompress_resource(u1* compressed, u1* uncompressed,
|
||||||
|
u4 uncompressed_size, const ImageStrings* strings, bool is_C_heap) {
|
||||||
|
bool has_header = false;
|
||||||
|
u1* decompressed_resource = compressed;
|
||||||
|
u1* compressed_resource = compressed;
|
||||||
|
|
||||||
|
// Resource could have been transformed by a stack of decompressors.
|
||||||
|
// Iterate and decompress resources until there is no more header.
|
||||||
|
do {
|
||||||
|
ResourceHeader _header;
|
||||||
|
memcpy(&_header, compressed_resource, sizeof (ResourceHeader));
|
||||||
|
has_header = _header._magic == ResourceHeader::resource_header_magic;
|
||||||
|
if (has_header) {
|
||||||
|
// decompressed_resource array contains the result of decompression
|
||||||
|
// when a resource content is terminal, it means that it is an actual resource,
|
||||||
|
// not an intermediate not fully uncompressed content. In this case
|
||||||
|
// the resource is allocated as an mtClass, otherwise as an mtOther
|
||||||
|
decompressed_resource = is_C_heap && _header._is_terminal ?
|
||||||
|
NEW_C_HEAP_ARRAY(u1, _header._uncompressed_size, mtClass) :
|
||||||
|
NEW_C_HEAP_ARRAY(u1, _header._uncompressed_size, mtOther);
|
||||||
|
// Retrieve the decompressor name
|
||||||
|
const char* decompressor_name = strings->get(_header._decompressor_name_offset);
|
||||||
|
if (decompressor_name == NULL) warning("image decompressor not found\n");
|
||||||
|
guarantee(decompressor_name, "image decompressor not found");
|
||||||
|
// Retrieve the decompressor instance
|
||||||
|
ImageDecompressor* decompressor = get_decompressor(decompressor_name);
|
||||||
|
if (decompressor == NULL) {
|
||||||
|
warning("image decompressor %s not found\n", decompressor_name);
|
||||||
|
}
|
||||||
|
guarantee(decompressor, "image decompressor not found");
|
||||||
|
u1* compressed_resource_base = compressed_resource;
|
||||||
|
compressed_resource += ResourceHeader::resource_header_length;
|
||||||
|
// Ask the decompressor to decompress the compressed content
|
||||||
|
decompressor->decompress_resource(compressed_resource, decompressed_resource,
|
||||||
|
&_header, strings);
|
||||||
|
if (compressed_resource_base != compressed) {
|
||||||
|
FREE_C_HEAP_ARRAY(char, compressed_resource_base);
|
||||||
|
}
|
||||||
|
compressed_resource = decompressed_resource;
|
||||||
|
}
|
||||||
|
} while (has_header);
|
||||||
|
memcpy(uncompressed, decompressed_resource, uncompressed_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zip decompressor
|
||||||
|
|
||||||
|
void ZipDecompressor::decompress_resource(u1* data, u1* uncompressed,
|
||||||
|
ResourceHeader* header, const ImageStrings* strings) {
|
||||||
|
char* msg = NULL;
|
||||||
|
jboolean res = ClassLoader::decompress(data, header->_size, uncompressed,
|
||||||
|
header->_uncompressed_size, &msg);
|
||||||
|
if (!res) warning("decompression failed due to %s\n", msg);
|
||||||
|
guarantee(res, "decompression failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
// END Zip Decompressor
|
137
hotspot/src/share/vm/classfile/imageDecompressor.hpp
Normal file
137
hotspot/src/share/vm/classfile/imageDecompressor.hpp
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SHARE_VM_CLASSFILE_IMAGEDECOMPRESSOR_HPP
|
||||||
|
#define SHARE_VM_CLASSFILE_IMAGEDECOMPRESSOR_HPP
|
||||||
|
|
||||||
|
#include "runtime/thread.inline.hpp"
|
||||||
|
#include "precompiled.hpp"
|
||||||
|
#include "classfile/classLoader.hpp"
|
||||||
|
#include "classfile/imageFile.hpp"
|
||||||
|
#include "classfile/symbolTable.hpp"
|
||||||
|
#include "oops/symbol.hpp"
|
||||||
|
#include "utilities/growableArray.hpp"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compressed resources located in image have an header.
|
||||||
|
* This header contains:
|
||||||
|
* - _magic: A magic u4, required to retrieved the header in the compressed content
|
||||||
|
* - _size: The size of the compressed resource.
|
||||||
|
* - _uncompressed_size: The uncompressed size of the compressed resource.
|
||||||
|
* - _decompressor_name_offset: The ImageDecompressor instance name StringsTable offset.
|
||||||
|
* - _decompressor_config_offset: StringsTable offset of configuration that could be needed by
|
||||||
|
* the decompressor in order to decompress.
|
||||||
|
* - _is_terminal: 1: the compressed content is terminal. Uncompressing it would
|
||||||
|
* create the actual resource. 0: the compressed content is not terminal. Uncompressing it
|
||||||
|
* will result in a compressed content to be decompressed (This occurs when a stack of compressors
|
||||||
|
* have been used to compress the resource.
|
||||||
|
*/
|
||||||
|
struct ResourceHeader {
|
||||||
|
/* Length of header, needed to retrieve content offset */
|
||||||
|
static const u1 resource_header_length = 21;
|
||||||
|
/* magic bytes that identifies a compressed resource header*/
|
||||||
|
static const u4 resource_header_magic = 0xCAFEFAFA;
|
||||||
|
u4 _magic; // Resource header
|
||||||
|
u4 _size; // Resource size
|
||||||
|
u4 _uncompressed_size; // Expected uncompressed size
|
||||||
|
u4 _decompressor_name_offset; // Strings table decompressor offset
|
||||||
|
u4 _decompressor_config_offset; // Strings table config offset
|
||||||
|
u1 _is_terminal; // Last decompressor 1, otherwise 0.
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Resources located in jimage file can be compressed. Compression occurs at
|
||||||
|
* jimage file creation time. When compressed a resource is added an header that
|
||||||
|
* contains the name of the compressor that compressed it.
|
||||||
|
* Various compression strategies can be applied to compress a resource.
|
||||||
|
* The same resource can even be compressed multiple time by a stack of compressors.
|
||||||
|
* At runtime, a resource is decompressed in a loop until there is no more header
|
||||||
|
* meaning that the resource is equivalent to the not compressed resource.
|
||||||
|
* In each iteration, the name of the compressor located in the current header
|
||||||
|
* is used to retrieve the associated instance of ImageDecompressor.
|
||||||
|
* For example “zip” is the name of the compressor that compresses resources
|
||||||
|
* using the zip algorithm. The ZipDecompressor class name is also “zip”.
|
||||||
|
* ImageDecompressor instances are retrieved from a static array in which
|
||||||
|
* they are registered.
|
||||||
|
*/
|
||||||
|
class ImageDecompressor: public CHeapObj<mtClass> {
|
||||||
|
|
||||||
|
private:
|
||||||
|
const Symbol* _name;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Array of concrete decompressors. This array is used to retrieve the decompressor
|
||||||
|
* that can handle resource decompression.
|
||||||
|
*/
|
||||||
|
static GrowableArray<ImageDecompressor*>* _decompressors;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Identifier of a decompressor. This name is the identification key to retrieve
|
||||||
|
* decompressor from a resource header.
|
||||||
|
*/
|
||||||
|
inline const Symbol* get_name() const { return _name; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ImageDecompressor(const Symbol* name) : _name(name) {
|
||||||
|
}
|
||||||
|
virtual void decompress_resource(u1* data, u1* uncompressed,
|
||||||
|
ResourceHeader* header, const ImageStrings* strings) = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
inline static void add_decompressor(ImageDecompressor* decompressor) {
|
||||||
|
_decompressors->append(decompressor);
|
||||||
|
}
|
||||||
|
inline static ImageDecompressor* get_decompressor(const char * decompressor_name) {
|
||||||
|
Thread* THREAD = Thread::current();
|
||||||
|
TempNewSymbol sym = SymbolTable::new_symbol(decompressor_name,
|
||||||
|
(int) strlen(decompressor_name), CHECK_NULL);
|
||||||
|
if (HAS_PENDING_EXCEPTION) {
|
||||||
|
warning("can't create symbol\n");
|
||||||
|
CLEAR_PENDING_EXCEPTION;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < _decompressors->length(); i++) {
|
||||||
|
ImageDecompressor* decompressor = _decompressors->at(i);
|
||||||
|
if (decompressor->get_name()->fast_compare(sym) == 0) {
|
||||||
|
return decompressor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
guarantee(false, "No decompressor found.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
static void decompress_resource(u1* compressed, u1* uncompressed,
|
||||||
|
u4 uncompressed_size, const ImageStrings* strings, bool is_C_heap);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Zip decompressor.
|
||||||
|
*/
|
||||||
|
class ZipDecompressor : public ImageDecompressor {
|
||||||
|
public:
|
||||||
|
ZipDecompressor(const Symbol* sym) : ImageDecompressor(sym) { }
|
||||||
|
void decompress_resource(u1* data, u1* uncompressed, ResourceHeader* header,
|
||||||
|
const ImageStrings* strings);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SHARE_VM_CLASSFILE_IMAGEDECOMPRESSOR_HPP
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -23,77 +23,311 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
|
#include "classfile/imageDecompressor.hpp"
|
||||||
#include "classfile/imageFile.hpp"
|
#include "classfile/imageFile.hpp"
|
||||||
|
#include "memory/resourceArea.hpp"
|
||||||
|
#include "runtime/mutex.hpp"
|
||||||
|
#include "runtime/mutexLocker.hpp"
|
||||||
#include "runtime/os.inline.hpp"
|
#include "runtime/os.inline.hpp"
|
||||||
#include "utilities/bytes.hpp"
|
#include "utilities/endian.hpp"
|
||||||
|
#include "utilities/growableArray.hpp"
|
||||||
|
|
||||||
|
// Image files are an alternate file format for storing classes and resources. The
|
||||||
|
// goal is to supply file access which is faster and smaller than the jar format.
|
||||||
|
//
|
||||||
|
// (More detailed nodes in the header.)
|
||||||
|
//
|
||||||
|
|
||||||
// Compute the Perfect Hashing hash code for the supplied string.
|
// Compute the Perfect Hashing hash code for the supplied UTF-8 string.
|
||||||
u4 ImageStrings::hash_code(const char* string, u4 seed) {
|
s4 ImageStrings::hash_code(const char* string, s4 seed) {
|
||||||
|
// Access bytes as unsigned.
|
||||||
u1* bytes = (u1*)string;
|
u1* bytes = (u1*)string;
|
||||||
|
|
||||||
// Compute hash code.
|
// Compute hash code.
|
||||||
for (u1 byte = *bytes++; byte; byte = *bytes++) {
|
for (u1 byte = *bytes++; byte; byte = *bytes++) {
|
||||||
seed = (seed * HASH_MULTIPLIER) ^ byte;
|
seed = (seed * HASH_MULTIPLIER) ^ byte;
|
||||||
}
|
}
|
||||||
|
// Ensure the result is not signed.
|
||||||
// Ensure the result is unsigned.
|
|
||||||
return seed & 0x7FFFFFFF;
|
return seed & 0x7FFFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test to see if string begins with start. If so returns remaining portion
|
// Match up a string in a perfect hash table. Result still needs validation
|
||||||
// of string. Otherwise, NULL.
|
// for precise match (false positive.)
|
||||||
|
s4 ImageStrings::find(Endian* endian, const char* name, s4* redirect, u4 length) {
|
||||||
|
// If the table is empty, then short cut.
|
||||||
|
if (redirect == NULL || length == 0) {
|
||||||
|
return NOT_FOUND;
|
||||||
|
}
|
||||||
|
// Compute the basic perfect hash for name.
|
||||||
|
s4 hash_code = ImageStrings::hash_code(name);
|
||||||
|
// Modulo table size.
|
||||||
|
s4 index = hash_code % length;
|
||||||
|
// Get redirect entry.
|
||||||
|
// value == 0 then not found
|
||||||
|
// value < 0 then -1 - value is true index
|
||||||
|
// value > 0 then value is seed for recomputing hash.
|
||||||
|
s4 value = endian->get(redirect[index]);
|
||||||
|
// if recompute is required.
|
||||||
|
if (value > 0) {
|
||||||
|
// Entry collision value, need to recompute hash.
|
||||||
|
hash_code = ImageStrings::hash_code(name, value);
|
||||||
|
// Modulo table size.
|
||||||
|
return hash_code % length;
|
||||||
|
} else if (value < 0) {
|
||||||
|
// Compute direct index.
|
||||||
|
return -1 - value;
|
||||||
|
}
|
||||||
|
// No entry found.
|
||||||
|
return NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test to see if UTF-8 string begins with the start UTF-8 string. If so,
|
||||||
|
// return non-NULL address of remaining portion of string. Otherwise, return
|
||||||
|
// NULL. Used to test sections of a path without copying from image string
|
||||||
|
// table.
|
||||||
const char* ImageStrings::starts_with(const char* string, const char* start) {
|
const char* ImageStrings::starts_with(const char* string, const char* start) {
|
||||||
char ch1, ch2;
|
char ch1, ch2;
|
||||||
|
|
||||||
// Match up the strings the best we can.
|
// Match up the strings the best we can.
|
||||||
while ((ch1 = *string) && (ch2 = *start)) {
|
while ((ch1 = *string) && (ch2 = *start)) {
|
||||||
if (ch1 != ch2) {
|
if (ch1 != ch2) {
|
||||||
// Mismatch, return NULL.
|
// Mismatch, return NULL.
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
// Next characters.
|
||||||
string++, start++;
|
string++, start++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return remainder of string.
|
// Return remainder of string.
|
||||||
return string;
|
return string;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageLocation::ImageLocation(u1* data) {
|
// Inflates the attribute stream into individual values stored in the long
|
||||||
|
// array _attributes. This allows an attribute value to be quickly accessed by
|
||||||
|
// direct indexing. Unspecified values default to zero (from constructor.)
|
||||||
|
void ImageLocation::set_data(u1* data) {
|
||||||
// Deflate the attribute stream into an array of attributes.
|
// Deflate the attribute stream into an array of attributes.
|
||||||
memset(_attributes, 0, sizeof(_attributes));
|
|
||||||
u1 byte;
|
u1 byte;
|
||||||
|
// Repeat until end header is found.
|
||||||
while ((byte = *data) != ATTRIBUTE_END) {
|
while ((byte = *data)) {
|
||||||
|
// Extract kind from header byte.
|
||||||
u1 kind = attribute_kind(byte);
|
u1 kind = attribute_kind(byte);
|
||||||
|
guarantee(kind < ATTRIBUTE_COUNT, "invalid image location attribute");
|
||||||
|
// Extract length of data (in bytes).
|
||||||
u1 n = attribute_length(byte);
|
u1 n = attribute_length(byte);
|
||||||
assert(kind < ATTRIBUTE_COUNT, "invalid image location attribute");
|
// Read value (most significant first.)
|
||||||
_attributes[kind] = attribute_value(data + 1, n);
|
_attributes[kind] = attribute_value(data + 1, n);
|
||||||
|
// Position to next attribute by skipping attribute header and data bytes.
|
||||||
data += n + 1;
|
data += n + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageFile::ImageFile(const char* name) {
|
// Zero all attribute values.
|
||||||
// Copy the image file name.
|
void ImageLocation::clear_data() {
|
||||||
_name = NEW_C_HEAP_ARRAY(char, strlen(name)+1, mtClass);
|
// Set defaults to zero.
|
||||||
strcpy(_name, name);
|
memset(_attributes, 0, sizeof(_attributes));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImageModuleData constructor maps out sub-tables for faster access.
|
||||||
|
ImageModuleData::ImageModuleData(const ImageFileReader* image_file,
|
||||||
|
const char* module_data_name) :
|
||||||
|
_image_file(image_file),
|
||||||
|
_endian(image_file->endian()),
|
||||||
|
_strings(image_file->get_strings()) {
|
||||||
|
// Retrieve the resource containing the module data for the image file.
|
||||||
|
ImageLocation location;
|
||||||
|
bool found = image_file->find_location(module_data_name, location);
|
||||||
|
guarantee(found, "missing module data");
|
||||||
|
u8 data_size = location.get_attribute(ImageLocation::ATTRIBUTE_UNCOMPRESSED);
|
||||||
|
_data = (u1*)NEW_C_HEAP_ARRAY(char, data_size, mtClass);
|
||||||
|
_image_file->get_resource(location, _data);
|
||||||
|
// Map out the header.
|
||||||
|
_header = (Header*)_data;
|
||||||
|
// Get the package to module entry count.
|
||||||
|
u4 ptm_count = _header->ptm_count(_endian);
|
||||||
|
// Get the module to package entry count.
|
||||||
|
u4 mtp_count = _header->mtp_count(_endian);
|
||||||
|
// Compute the offset of the package to module perfect hash redirect.
|
||||||
|
u4 ptm_redirect_offset = sizeof(Header);
|
||||||
|
// Compute the offset of the package to module data.
|
||||||
|
u4 ptm_data_offset = ptm_redirect_offset + ptm_count * sizeof(s4);
|
||||||
|
// Compute the offset of the module to package perfect hash redirect.
|
||||||
|
u4 mtp_redirect_offset = ptm_data_offset + ptm_count * sizeof(PTMData);
|
||||||
|
// Compute the offset of the module to package data.
|
||||||
|
u4 mtp_data_offset = mtp_redirect_offset + mtp_count * sizeof(s4);
|
||||||
|
// Compute the offset of the module to package tables.
|
||||||
|
u4 mtp_packages_offset = mtp_data_offset + mtp_count * sizeof(MTPData);
|
||||||
|
// Compute the address of the package to module perfect hash redirect.
|
||||||
|
_ptm_redirect = (s4*)(_data + ptm_redirect_offset);
|
||||||
|
// Compute the address of the package to module data.
|
||||||
|
_ptm_data = (PTMData*)(_data + ptm_data_offset);
|
||||||
|
// Compute the address of the module to package perfect hash redirect.
|
||||||
|
_mtp_redirect = (s4*)(_data + mtp_redirect_offset);
|
||||||
|
// Compute the address of the module to package data.
|
||||||
|
_mtp_data = (MTPData*)(_data + mtp_data_offset);
|
||||||
|
// Compute the address of the module to package tables.
|
||||||
|
_mtp_packages = (s4*)(_data + mtp_packages_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release module data resource.
|
||||||
|
ImageModuleData::~ImageModuleData() {
|
||||||
|
if (_data != NULL) {
|
||||||
|
FREE_C_HEAP_ARRAY(u1, _data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the name of the module data resource. Ex. "./lib/modules/file.jimage"
|
||||||
|
// yields "file.jdata"
|
||||||
|
void ImageModuleData::module_data_name(char* buffer, const char* image_file_name) {
|
||||||
|
// Locate the last slash in the file name path.
|
||||||
|
const char* slash = strrchr(image_file_name, os::file_separator()[0]);
|
||||||
|
// Trim the path to name and extension.
|
||||||
|
const char* name = slash != NULL ? slash + 1 : (char *)image_file_name;
|
||||||
|
// Locate the extension period.
|
||||||
|
const char* dot = strrchr(name, '.');
|
||||||
|
guarantee(dot, "missing extension on jimage name");
|
||||||
|
// Trim to only base name.
|
||||||
|
int length = dot - name;
|
||||||
|
strncpy(buffer, name, length);
|
||||||
|
buffer[length] = '\0';
|
||||||
|
// Append extension.
|
||||||
|
strcat(buffer, ".jdata");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the module in which a package resides. Returns NULL if not found.
|
||||||
|
const char* ImageModuleData::package_to_module(const char* package_name) {
|
||||||
|
// Search the package to module table.
|
||||||
|
s4 index = ImageStrings::find(_endian, package_name, _ptm_redirect,
|
||||||
|
_header->ptm_count(_endian));
|
||||||
|
// If entry is found.
|
||||||
|
if (index != ImageStrings::NOT_FOUND) {
|
||||||
|
// Retrieve the package to module entry.
|
||||||
|
PTMData* data = _ptm_data + index;
|
||||||
|
// Verify that it is the correct data.
|
||||||
|
if (strcmp(package_name, get_string(data->name_offset(_endian))) != 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
// Return the module name.
|
||||||
|
return get_string(data->module_name_offset(_endian));
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns all the package names in a module. Returns NULL if module not found.
|
||||||
|
GrowableArray<const char*>* ImageModuleData::module_to_packages(const char* module_name) {
|
||||||
|
// Search the module to package table.
|
||||||
|
s4 index = ImageStrings::find(_endian, module_name, _mtp_redirect,
|
||||||
|
_header->mtp_count(_endian));
|
||||||
|
// If entry is found.
|
||||||
|
if (index != ImageStrings::NOT_FOUND) {
|
||||||
|
// Retrieve the module to package entry.
|
||||||
|
MTPData* data = _mtp_data + index;
|
||||||
|
// Verify that it is the correct data.
|
||||||
|
if (strcmp(module_name, get_string(data->name_offset(_endian))) != 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
// Construct an array of all the package entries.
|
||||||
|
GrowableArray<const char*>* packages = new GrowableArray<const char*>();
|
||||||
|
s4 package_offset = data->package_offset(_endian);
|
||||||
|
for (u4 i = 0; i < data->package_count(_endian); i++) {
|
||||||
|
u4 package_name_offset = mtp_package(package_offset + i);
|
||||||
|
const char* package_name = get_string(package_name_offset);
|
||||||
|
packages->append(package_name);
|
||||||
|
}
|
||||||
|
return packages;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Table to manage multiple opens of an image file.
|
||||||
|
GrowableArray<ImageFileReader*>* ImageFileReader::_reader_table =
|
||||||
|
new(ResourceObj::C_HEAP, mtInternal) GrowableArray<ImageFileReader*>(2, true);
|
||||||
|
|
||||||
|
// Open an image file, reuse structure if file already open.
|
||||||
|
ImageFileReader* ImageFileReader::open(const char* name, bool big_endian) {
|
||||||
|
// Lock out _reader_table.
|
||||||
|
MutexLocker ml(ImageFileReaderTable_lock);
|
||||||
|
ImageFileReader* reader;
|
||||||
|
// Search for an exist image file.
|
||||||
|
for (int i = 0; i < _reader_table->length(); i++) {
|
||||||
|
// Retrieve table entry.
|
||||||
|
reader = _reader_table->at(i);
|
||||||
|
// If name matches, then reuse (bump up use count.)
|
||||||
|
if (strcmp(reader->name(), name) == 0) {
|
||||||
|
reader->inc_use();
|
||||||
|
return reader;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Need a new image reader.
|
||||||
|
reader = new ImageFileReader(name, big_endian);
|
||||||
|
bool opened = reader->open();
|
||||||
|
// If failed to open.
|
||||||
|
if (!opened) {
|
||||||
|
delete reader;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
// Bump use count and add to table.
|
||||||
|
reader->inc_use();
|
||||||
|
_reader_table->append(reader);
|
||||||
|
return reader;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close an image file if the file is not in use elsewhere.
|
||||||
|
void ImageFileReader::close(ImageFileReader *reader) {
|
||||||
|
// Lock out _reader_table.
|
||||||
|
MutexLocker ml(ImageFileReaderTable_lock);
|
||||||
|
// If last use then remove from table and then close.
|
||||||
|
if (reader->dec_use()) {
|
||||||
|
_reader_table->remove(reader);
|
||||||
|
delete reader;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return an id for the specifed ImageFileReader.
|
||||||
|
u8 ImageFileReader::readerToID(ImageFileReader *reader) {
|
||||||
|
// ID is just the cloaked reader address.
|
||||||
|
return (u8)reader;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the image id.
|
||||||
|
bool ImageFileReader::idCheck(u8 id) {
|
||||||
|
// Make sure the ID is a managed (_reader_table) reader.
|
||||||
|
MutexLocker ml(ImageFileReaderTable_lock);
|
||||||
|
return _reader_table->contains((ImageFileReader*)id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return an id for the specifed ImageFileReader.
|
||||||
|
ImageFileReader* ImageFileReader::idToReader(u8 id) {
|
||||||
|
#ifdef PRODUCT
|
||||||
|
// Fast convert.
|
||||||
|
return (ImageFileReader*)id;
|
||||||
|
#else
|
||||||
|
// Do a slow check before fast convert.
|
||||||
|
return idCheck(id) ? (ImageFileReader*)id : NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructor intializes to a closed state.
|
||||||
|
ImageFileReader::ImageFileReader(const char* name, bool big_endian) {
|
||||||
|
// Copy the image file name.
|
||||||
|
_name = NEW_C_HEAP_ARRAY(char, strlen(name) + 1, mtClass);
|
||||||
|
strcpy(_name, name);
|
||||||
// Initialize for a closed file.
|
// Initialize for a closed file.
|
||||||
_fd = -1;
|
_fd = -1;
|
||||||
_memory_mapped = true;
|
_endian = Endian::get_handler(big_endian);
|
||||||
_index_data = NULL;
|
_index_data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageFile::~ImageFile() {
|
// Close image and free up data structures.
|
||||||
|
ImageFileReader::~ImageFileReader() {
|
||||||
// Ensure file is closed.
|
// Ensure file is closed.
|
||||||
close();
|
close();
|
||||||
|
|
||||||
// Free up name.
|
// Free up name.
|
||||||
FREE_C_HEAP_ARRAY(char, _name);
|
if (_name != NULL) {
|
||||||
|
FREE_C_HEAP_ARRAY(char, _name);
|
||||||
|
_name = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ImageFile::open() {
|
// Open image file for read access.
|
||||||
|
bool ImageFileReader::open() {
|
||||||
// If file exists open for reading.
|
// If file exists open for reading.
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (os::stat(_name, &st) != 0 ||
|
if (os::stat(_name, &st) != 0 ||
|
||||||
@ -101,186 +335,212 @@ bool ImageFile::open() {
|
|||||||
(_fd = os::open(_name, 0, O_RDONLY)) == -1) {
|
(_fd = os::open(_name, 0, O_RDONLY)) == -1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// Retrieve the file size.
|
||||||
// Read image file header and verify.
|
_file_size = (u8)st.st_size;
|
||||||
u8 header_size = sizeof(ImageHeader);
|
// Read image file header and verify it has a valid header.
|
||||||
if (os::read(_fd, &_header, header_size) != header_size ||
|
size_t header_size = sizeof(ImageHeader);
|
||||||
_header._magic != IMAGE_MAGIC ||
|
if (_file_size < header_size ||
|
||||||
_header._major_version != MAJOR_VERSION ||
|
!read_at((u1*)&_header, header_size, 0) ||
|
||||||
_header._minor_version != MINOR_VERSION) {
|
_header.magic(_endian) != IMAGE_MAGIC ||
|
||||||
|
_header.major_version(_endian) != MAJOR_VERSION ||
|
||||||
|
_header.minor_version(_endian) != MINOR_VERSION) {
|
||||||
close();
|
close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// Size of image index.
|
||||||
// Memory map index.
|
|
||||||
_index_size = index_size();
|
_index_size = index_size();
|
||||||
_index_data = (u1*)os::map_memory(_fd, _name, 0, NULL, _index_size, true, false);
|
// Make sure file is large enough to contain the index.
|
||||||
|
if (_file_size < _index_size) {
|
||||||
// Failing that, read index into C memory.
|
return false;
|
||||||
if (_index_data == NULL) {
|
|
||||||
_memory_mapped = false;
|
|
||||||
_index_data = NEW_RESOURCE_ARRAY(u1, _index_size);
|
|
||||||
|
|
||||||
if (os::seek_to_file_offset(_fd, 0) == -1) {
|
|
||||||
close();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (os::read(_fd, _index_data, _index_size) != _index_size) {
|
|
||||||
close();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
// Determine how much of the image is memory mapped.
|
||||||
// Used to advance a pointer, unstructured.
|
off_t map_size = (off_t)(MemoryMapImage ? _file_size : _index_size);
|
||||||
#undef nextPtr
|
// Memory map image (minimally the index.)
|
||||||
#define nextPtr(base, fromType, count, toType) (toType*)((fromType*)(base) + (count))
|
_index_data = (u1*)os::map_memory(_fd, _name, 0, NULL, map_size, true, false);
|
||||||
// Pull tables out from the index.
|
guarantee(_index_data, "image file not memory mapped");
|
||||||
_redirect_table = nextPtr(_index_data, u1, header_size, s4);
|
// Retrieve length of index perfect hash table.
|
||||||
_offsets_table = nextPtr(_redirect_table, s4, _header._location_count, u4);
|
u4 length = table_length();
|
||||||
_location_bytes = nextPtr(_offsets_table, u4, _header._location_count, u1);
|
// Compute offset of the perfect hash table redirect table.
|
||||||
_string_bytes = nextPtr(_location_bytes, u1, _header._locations_size, u1);
|
u4 redirect_table_offset = (u4)header_size;
|
||||||
#undef nextPtr
|
// Compute offset of index attribute offsets.
|
||||||
|
u4 offsets_table_offset = redirect_table_offset + length * sizeof(s4);
|
||||||
|
// Compute offset of index location attribute data.
|
||||||
|
u4 location_bytes_offset = offsets_table_offset + length * sizeof(u4);
|
||||||
|
// Compute offset of index string table.
|
||||||
|
u4 string_bytes_offset = location_bytes_offset + locations_size();
|
||||||
|
// Compute address of the perfect hash table redirect table.
|
||||||
|
_redirect_table = (s4*)(_index_data + redirect_table_offset);
|
||||||
|
// Compute address of index attribute offsets.
|
||||||
|
_offsets_table = (u4*)(_index_data + offsets_table_offset);
|
||||||
|
// Compute address of index location attribute data.
|
||||||
|
_location_bytes = _index_data + location_bytes_offset;
|
||||||
|
// Compute address of index string table.
|
||||||
|
_string_bytes = _index_data + string_bytes_offset;
|
||||||
// Successful open.
|
// Successful open.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageFile::close() {
|
// Close image file.
|
||||||
|
void ImageFileReader::close() {
|
||||||
// Dealllocate the index.
|
// Dealllocate the index.
|
||||||
if (_index_data) {
|
if (_index_data != NULL) {
|
||||||
if (_memory_mapped) {
|
os::unmap_memory((char*)_index_data, _index_size);
|
||||||
os::unmap_memory((char*)_index_data, _index_size);
|
|
||||||
} else {
|
|
||||||
FREE_RESOURCE_ARRAY(u1, _index_data, _index_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
_index_data = NULL;
|
_index_data = NULL;
|
||||||
}
|
}
|
||||||
|
// Close file.
|
||||||
// close file.
|
|
||||||
if (_fd != -1) {
|
if (_fd != -1) {
|
||||||
os::close(_fd);
|
os::close(_fd);
|
||||||
_fd = -1;
|
_fd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the attribute stream for a named resourced.
|
// Read directly from the file.
|
||||||
u1* ImageFile::find_location_data(const char* path) const {
|
bool ImageFileReader::read_at(u1* data, u8 size, u8 offset) const {
|
||||||
// Compute hash.
|
return os::read_at(_fd, data, size, offset) == size;
|
||||||
u4 hash = ImageStrings::hash_code(path) % _header._location_count;
|
|
||||||
s4 redirect = _redirect_table[hash];
|
|
||||||
|
|
||||||
if (!redirect) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
u4 index;
|
|
||||||
|
|
||||||
if (redirect < 0) {
|
|
||||||
// If no collision.
|
|
||||||
index = -redirect - 1;
|
|
||||||
} else {
|
|
||||||
// If collision, recompute hash code.
|
|
||||||
index = ImageStrings::hash_code(path, redirect) % _header._location_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(index < _header._location_count, "index exceeds location count");
|
|
||||||
u4 offset = _offsets_table[index];
|
|
||||||
assert(offset < _header._locations_size, "offset exceeds location attributes size");
|
|
||||||
|
|
||||||
if (offset == 0) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _location_bytes + offset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that a found location matches the supplied path.
|
// Find the location attributes associated with the path. Returns true if
|
||||||
bool ImageFile::verify_location(ImageLocation& location, const char* path) const {
|
// the location is found, false otherwise.
|
||||||
// Retrieve each path component string.
|
bool ImageFileReader::find_location(const char* path, ImageLocation& location) const {
|
||||||
ImageStrings strings(_string_bytes, _header._strings_size);
|
// Locate the entry in the index perfect hash table.
|
||||||
// Match a path with each subcomponent without concatenation (copy).
|
s4 index = ImageStrings::find(_endian, path, _redirect_table, table_length());
|
||||||
// Match up path parent.
|
// If is found.
|
||||||
|
if (index != ImageStrings::NOT_FOUND) {
|
||||||
|
// Get address of first byte of location attribute stream.
|
||||||
|
u1* data = get_location_data(index);
|
||||||
|
// Expand location attributes.
|
||||||
|
location.set_data(data);
|
||||||
|
// Make sure result is not a false positive.
|
||||||
|
return verify_location(location, path);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble the location path from the string fragments indicated in the location attributes.
|
||||||
|
void ImageFileReader::location_path(ImageLocation& location, char* path, size_t max) const {
|
||||||
|
// Manage the image string table.
|
||||||
|
ImageStrings strings(_string_bytes, _header.strings_size(_endian));
|
||||||
|
// Position to first character of the path buffer.
|
||||||
|
char* next = path;
|
||||||
|
// Temp for string length.
|
||||||
|
size_t length;
|
||||||
|
// Get module string.
|
||||||
|
const char* module = location.get_attribute(ImageLocation::ATTRIBUTE_MODULE, strings);
|
||||||
|
// If module string is not empty string.
|
||||||
|
if (*module != '\0') {
|
||||||
|
// Get length of module name.
|
||||||
|
length = strlen(module);
|
||||||
|
// Make sure there is no buffer overflow.
|
||||||
|
guarantee(next - path + length + 2 < max, "buffer overflow");
|
||||||
|
// Append '/module/'.
|
||||||
|
*next++ = '/';
|
||||||
|
strcpy(next, module); next += length;
|
||||||
|
*next++ = '/';
|
||||||
|
}
|
||||||
|
// Get parent (package) string.
|
||||||
const char* parent = location.get_attribute(ImageLocation::ATTRIBUTE_PARENT, strings);
|
const char* parent = location.get_attribute(ImageLocation::ATTRIBUTE_PARENT, strings);
|
||||||
const char* next = ImageStrings::starts_with(path, parent);
|
// If parent string is not empty string.
|
||||||
// Continue only if a complete match.
|
if (*parent != '\0') {
|
||||||
if (!next) return false;
|
// Get length of module string.
|
||||||
// Match up path base.
|
length = strlen(parent);
|
||||||
|
// Make sure there is no buffer overflow.
|
||||||
|
guarantee(next - path + length + 1 < max, "buffer overflow");
|
||||||
|
// Append 'patent/' .
|
||||||
|
strcpy(next, parent); next += length;
|
||||||
|
*next++ = '/';
|
||||||
|
}
|
||||||
|
// Get base name string.
|
||||||
const char* base = location.get_attribute(ImageLocation::ATTRIBUTE_BASE, strings);
|
const char* base = location.get_attribute(ImageLocation::ATTRIBUTE_BASE, strings);
|
||||||
next = ImageStrings::starts_with(next, base);
|
// Get length of base name.
|
||||||
// Continue only if a complete match.
|
length = strlen(base);
|
||||||
if (!next) return false;
|
// Make sure there is no buffer overflow.
|
||||||
// Match up path extension.
|
guarantee(next - path + length < max, "buffer overflow");
|
||||||
|
// Append base name.
|
||||||
|
strcpy(next, base); next += length;
|
||||||
|
// Get extension string.
|
||||||
const char* extension = location.get_attribute(ImageLocation::ATTRIBUTE_EXTENSION, strings);
|
const char* extension = location.get_attribute(ImageLocation::ATTRIBUTE_EXTENSION, strings);
|
||||||
next = ImageStrings::starts_with(next, extension);
|
// If extension string is not empty string.
|
||||||
|
if (*extension != '\0') {
|
||||||
|
// Get length of extension string.
|
||||||
|
length = strlen(extension);
|
||||||
|
// Make sure there is no buffer overflow.
|
||||||
|
guarantee(next - path + length + 1 < max, "buffer overflow");
|
||||||
|
// Append '.extension' .
|
||||||
|
*next++ = '.';
|
||||||
|
strcpy(next, extension); next += length;
|
||||||
|
}
|
||||||
|
// Make sure there is no buffer overflow.
|
||||||
|
guarantee((size_t)(next - path) < max, "buffer overflow");
|
||||||
|
// Terminate string.
|
||||||
|
*next = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that a found location matches the supplied path (without copying.)
|
||||||
|
bool ImageFileReader::verify_location(ImageLocation& location, const char* path) const {
|
||||||
|
// Manage the image string table.
|
||||||
|
ImageStrings strings(_string_bytes, _header.strings_size(_endian));
|
||||||
|
// Position to first character of the path string.
|
||||||
|
const char* next = path;
|
||||||
|
// Get module name string.
|
||||||
|
const char* module = location.get_attribute(ImageLocation::ATTRIBUTE_MODULE, strings);
|
||||||
|
// If module string is not empty.
|
||||||
|
if (*module != '\0') {
|
||||||
|
// Compare '/module/' .
|
||||||
|
if (*next++ != '/') return false;
|
||||||
|
if (!(next = ImageStrings::starts_with(next, module))) return false;
|
||||||
|
if (*next++ != '/') return false;
|
||||||
|
}
|
||||||
|
// Get parent (package) string
|
||||||
|
const char* parent = location.get_attribute(ImageLocation::ATTRIBUTE_PARENT, strings);
|
||||||
|
// If parent string is not empty string.
|
||||||
|
if (*parent != '\0') {
|
||||||
|
// Compare 'parent/' .
|
||||||
|
if (!(next = ImageStrings::starts_with(next, parent))) return false;
|
||||||
|
if (*next++ != '/') return false;
|
||||||
|
}
|
||||||
|
// Get base name string.
|
||||||
|
const char* base = location.get_attribute(ImageLocation::ATTRIBUTE_BASE, strings);
|
||||||
|
// Compare with basne name.
|
||||||
|
if (!(next = ImageStrings::starts_with(next, base))) return false;
|
||||||
|
// Get extension string.
|
||||||
|
const char* extension = location.get_attribute(ImageLocation::ATTRIBUTE_EXTENSION, strings);
|
||||||
|
// If extension is not empty.
|
||||||
|
if (*extension != '\0') {
|
||||||
|
// Compare '.extension' .
|
||||||
|
if (*next++ != '.') return false;
|
||||||
|
if (!(next = ImageStrings::starts_with(next, extension))) return false;
|
||||||
|
}
|
||||||
// True only if complete match and no more characters.
|
// True only if complete match and no more characters.
|
||||||
return next && *next == '\0';
|
return *next == '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the resource for the supplied location.
|
// Return the resource data for the supplied location.
|
||||||
u1* ImageFile::get_resource(ImageLocation& location) const {
|
void ImageFileReader::get_resource(ImageLocation& location, u1* uncompressed_data) const {
|
||||||
// Retrieve the byte offset and size of the resource.
|
// Retrieve the byte offset and size of the resource.
|
||||||
u8 offset = _index_size + location.get_attribute(ImageLocation::ATTRIBUTE_OFFSET);
|
u8 offset = location.get_attribute(ImageLocation::ATTRIBUTE_OFFSET);
|
||||||
u8 size = location.get_attribute(ImageLocation::ATTRIBUTE_UNCOMPRESSED);
|
u8 uncompressed_size = location.get_attribute(ImageLocation::ATTRIBUTE_UNCOMPRESSED);
|
||||||
u8 compressed_size = location.get_attribute(ImageLocation::ATTRIBUTE_COMPRESSED);
|
u8 compressed_size = location.get_attribute(ImageLocation::ATTRIBUTE_COMPRESSED);
|
||||||
u8 read_size = compressed_size ? compressed_size : size;
|
if (compressed_size != 0) {
|
||||||
|
ResourceMark rm;
|
||||||
// Allocate space for the resource.
|
u1* compressed_data;
|
||||||
u1* data = NEW_RESOURCE_ARRAY(u1, read_size);
|
// If not memory mapped read in bytes.
|
||||||
|
if (!MemoryMapImage) {
|
||||||
bool is_read = os::read_at(_fd, data, read_size, offset) == read_size;
|
// Allocate buffer for compression.
|
||||||
guarantee(is_read, "error reading from image or short read");
|
compressed_data = NEW_RESOURCE_ARRAY(u1, compressed_size);
|
||||||
|
// Read bytes from offset beyond the image index.
|
||||||
// If not compressed, just return the data.
|
bool is_read = read_at(compressed_data, compressed_size, _index_size + offset);
|
||||||
if (!compressed_size) {
|
guarantee(is_read, "error reading from image or short read");
|
||||||
return data;
|
} else {
|
||||||
}
|
compressed_data = get_data_address() + offset;
|
||||||
|
|
||||||
u1* uncompressed = NEW_RESOURCE_ARRAY(u1, size);
|
|
||||||
char* msg = NULL;
|
|
||||||
jboolean res = ClassLoader::decompress(data, compressed_size, uncompressed, size, &msg);
|
|
||||||
if (!res) warning("decompression failed due to %s\n", msg);
|
|
||||||
guarantee(res, "decompression failed");
|
|
||||||
|
|
||||||
return uncompressed;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImageFile::get_resource(const char* path, u1*& buffer, u8& size) const {
|
|
||||||
buffer = NULL;
|
|
||||||
size = 0;
|
|
||||||
u1* data = find_location_data(path);
|
|
||||||
if (data) {
|
|
||||||
ImageLocation location(data);
|
|
||||||
if (verify_location(location, path)) {
|
|
||||||
size = location.get_attribute(ImageLocation::ATTRIBUTE_UNCOMPRESSED);
|
|
||||||
buffer = get_resource(location);
|
|
||||||
}
|
}
|
||||||
|
// Get image string table.
|
||||||
|
const ImageStrings strings = get_strings();
|
||||||
|
// Decompress resource.
|
||||||
|
ImageDecompressor::decompress_resource(compressed_data, uncompressed_data, uncompressed_size,
|
||||||
|
&strings, false);
|
||||||
|
} else {
|
||||||
|
// Read bytes from offset beyond the image index.
|
||||||
|
bool is_read = read_at(uncompressed_data, uncompressed_size, _index_size + offset);
|
||||||
|
guarantee(is_read, "error reading from image or short read");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GrowableArray<const char*>* ImageFile::packages(const char* name) {
|
|
||||||
char entry[JVM_MAXPATHLEN];
|
|
||||||
bool overflow = jio_snprintf(entry, sizeof(entry), "%s/packages.offsets", name) == -1;
|
|
||||||
guarantee(!overflow, "package name overflow");
|
|
||||||
|
|
||||||
u1* buffer;
|
|
||||||
u8 size;
|
|
||||||
|
|
||||||
get_resource(entry, buffer, size);
|
|
||||||
guarantee(buffer, "missing module packages reource");
|
|
||||||
ImageStrings strings(_string_bytes, _header._strings_size);
|
|
||||||
GrowableArray<const char*>* pkgs = new GrowableArray<const char*>();
|
|
||||||
int count = size / 4;
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
u4 offset = Bytes::get_Java_u4(buffer + (i*4));
|
|
||||||
const char* p = strings.get(offset);
|
|
||||||
pkgs->append(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
return pkgs;
|
|
||||||
}
|
|
||||||
|
@ -28,13 +28,15 @@
|
|||||||
#include "classfile/classLoader.hpp"
|
#include "classfile/classLoader.hpp"
|
||||||
#include "memory/allocation.hpp"
|
#include "memory/allocation.hpp"
|
||||||
#include "memory/allocation.inline.hpp"
|
#include "memory/allocation.inline.hpp"
|
||||||
|
#include "utilities/endian.hpp"
|
||||||
#include "utilities/globalDefinitions.hpp"
|
#include "utilities/globalDefinitions.hpp"
|
||||||
|
#include "utilities/growableArray.hpp"
|
||||||
|
|
||||||
// Image files are an alternate file format for storing classes and resources. The
|
// Image files are an alternate file format for storing classes and resources. The
|
||||||
// goal is to supply file access which is faster and smaller that the jar format.
|
// goal is to supply file access which is faster and smaller than the jar format.
|
||||||
// It should be noted that unlike jars information stored in an image is in native
|
// It should be noted that unlike jars, information stored in an image is in native
|
||||||
// endian format. This allows the image to be memory mapped into memory without
|
// endian format. This allows the image to be mapped into memory without endian
|
||||||
// endian translation. This also means that images are platform dependent.
|
// translation. This also means that images are platform dependent.
|
||||||
//
|
//
|
||||||
// Image files are structured as three sections;
|
// Image files are structured as three sections;
|
||||||
//
|
//
|
||||||
@ -42,7 +44,7 @@
|
|||||||
// | Header |
|
// | Header |
|
||||||
// +-----------+
|
// +-----------+
|
||||||
// | |
|
// | |
|
||||||
// | Directory |
|
// | Index |
|
||||||
// | |
|
// | |
|
||||||
// +-----------+
|
// +-----------+
|
||||||
// | |
|
// | |
|
||||||
@ -60,7 +62,11 @@
|
|||||||
// +------------+------------+
|
// +------------+------------+
|
||||||
// | Major Vers | Minor Vers |
|
// | Major Vers | Minor Vers |
|
||||||
// +------------+------------+
|
// +------------+------------+
|
||||||
// | Location Count |
|
// | Flags |
|
||||||
|
// +-------------------------+
|
||||||
|
// | Resource Count |
|
||||||
|
// +-------------------------+
|
||||||
|
// | Table Length |
|
||||||
// +-------------------------+
|
// +-------------------------+
|
||||||
// | Attributes Size |
|
// | Attributes Size |
|
||||||
// +-------------------------+
|
// +-------------------------+
|
||||||
@ -71,23 +77,24 @@
|
|||||||
// special file extension.
|
// special file extension.
|
||||||
// Major vers, minor vers - differences in version numbers indicate structural
|
// Major vers, minor vers - differences in version numbers indicate structural
|
||||||
// changes in the image.
|
// changes in the image.
|
||||||
// Location count - number of locations/resources in the file. This count is also
|
// Flags - various image wide flags (future).
|
||||||
// the length of lookup tables used in the directory.
|
// Resource count - number of resources in the file.
|
||||||
|
// Table length - the length of lookup tables used in the index.
|
||||||
// Attributes size - number of bytes in the region used to store location attribute
|
// Attributes size - number of bytes in the region used to store location attribute
|
||||||
// streams.
|
// streams.
|
||||||
// Strings size - the size of the region used to store strings used by the
|
// Strings size - the size of the region used to store strings used by the
|
||||||
// directory and meta data.
|
// index and meta data.
|
||||||
//
|
//
|
||||||
// The directory contains information related to resource lookup. The algorithm
|
// The index contains information related to resource lookup. The algorithm
|
||||||
// used for lookup is "A Practical Minimal Perfect Hashing Method"
|
// used for lookup is "A Practical Minimal Perfect Hashing Method"
|
||||||
// (http://homepages.dcc.ufmg.br/~nivio/papers/wea05.pdf). Given a path string
|
// (http://homepages.dcc.ufmg.br/~nivio/papers/wea05.pdf). Given a path string
|
||||||
// in the form <package>/<base>.<extension> return the resource location
|
// in the form /<module>/<package>/<base>.<extension> return the resource location
|
||||||
// information;
|
// information;
|
||||||
//
|
//
|
||||||
// redirectIndex = hash(path, DEFAULT_SEED) % count;
|
// redirectIndex = hash(path, DEFAULT_SEED) % table_length;
|
||||||
// redirect = redirectTable[redirectIndex];
|
// redirect = redirectTable[redirectIndex];
|
||||||
// if (redirect == 0) return not found;
|
// if (redirect == 0) return not found;
|
||||||
// locationIndex = redirect < 0 ? -1 - redirect : hash(path, redirect) % count;
|
// locationIndex = redirect < 0 ? -1 - redirect : hash(path, redirect) % table_length;
|
||||||
// location = locationTable[locationIndex];
|
// location = locationTable[locationIndex];
|
||||||
// if (!verify(location, path)) return not found;
|
// if (!verify(location, path)) return not found;
|
||||||
// return location;
|
// return location;
|
||||||
@ -97,7 +104,7 @@
|
|||||||
// other seeds. The verify function guarantees the found resource location is
|
// other seeds. The verify function guarantees the found resource location is
|
||||||
// indeed the resource we are looking for.
|
// indeed the resource we are looking for.
|
||||||
//
|
//
|
||||||
// The following is the format of the directory;
|
// The following is the format of the index;
|
||||||
//
|
//
|
||||||
// +-------------------+
|
// +-------------------+
|
||||||
// | Redirect Table |
|
// | Redirect Table |
|
||||||
@ -117,54 +124,74 @@
|
|||||||
// offsets. Zero indicates not found.
|
// offsets. Zero indicates not found.
|
||||||
// Attribute Offsets - Array of 32-bit unsigned values representing offsets into
|
// Attribute Offsets - Array of 32-bit unsigned values representing offsets into
|
||||||
// attribute data. Attribute offsets can be iterated to do a
|
// attribute data. Attribute offsets can be iterated to do a
|
||||||
// full survey of resources in the image.
|
// full survey of resources in the image. Offset of zero
|
||||||
|
// indicates no attributes.
|
||||||
// Attribute Data - Bytes representing compact attribute data for locations. (See
|
// Attribute Data - Bytes representing compact attribute data for locations. (See
|
||||||
// comments in ImageLocation.)
|
// comments in ImageLocation.)
|
||||||
// Strings - Collection of zero terminated UTF-8 strings used by the directory and
|
// Strings - Collection of zero terminated UTF-8 strings used by the index and
|
||||||
// image meta data. Each string is accessed by offset. Each string is
|
// image meta data. Each string is accessed by offset. Each string is
|
||||||
// unique. Offset zero is reserved for the empty string.
|
// unique. Offset zero is reserved for the empty string.
|
||||||
//
|
//
|
||||||
// Note that the memory mapped directory assumes 32 bit alignment of the image
|
// Note that the memory mapped index assumes 32 bit alignment of each component
|
||||||
// header, the redirect table and the attribute offsets.
|
// in the index.
|
||||||
|
//
|
||||||
|
// Endianness of an image.
|
||||||
|
// An image booted by hotspot is always in native endian. However, it is possible
|
||||||
|
// to read (by the JDK) in alternate endian format. Primarily, this is during
|
||||||
|
// cross platform scenarios. Ex, where javac needs to read an embedded image
|
||||||
|
// to access classes for crossing compilation.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
class ImageFileReader; // forward declaration
|
||||||
|
|
||||||
// Manage image file string table.
|
// Manage image file string table.
|
||||||
class ImageStrings {
|
class ImageStrings VALUE_OBJ_CLASS_SPEC {
|
||||||
private:
|
private:
|
||||||
// Data bytes for strings.
|
u1* _data; // Data bytes for strings.
|
||||||
u1* _data;
|
u4 _size; // Number of bytes in the string table.
|
||||||
// Number of bytes in the string table.
|
|
||||||
u4 _size;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Prime used to generate hash for Perfect Hashing.
|
enum {
|
||||||
static const u4 HASH_MULTIPLIER = 0x01000193;
|
// Not found result from find routine.
|
||||||
|
NOT_FOUND = -1,
|
||||||
|
// Prime used to generate hash for Perfect Hashing.
|
||||||
|
HASH_MULTIPLIER = 0x01000193
|
||||||
|
};
|
||||||
|
|
||||||
ImageStrings(u1* data, u4 size) : _data(data), _size(size) {}
|
ImageStrings(u1* data, u4 size) : _data(data), _size(size) {}
|
||||||
|
|
||||||
// Return the UTF-8 string beginning at offset.
|
// Return the UTF-8 string beginning at offset.
|
||||||
inline const char* get(u4 offset) const {
|
inline const char* get(u4 offset) const {
|
||||||
assert(offset < _size, "offset exceeds string table size");
|
guarantee(offset < _size, "offset exceeds string table size");
|
||||||
return (const char*)(_data + offset);
|
return (const char*)(_data + offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute the Perfect Hashing hash code for the supplied string.
|
// Compute the Perfect Hashing hash code for the supplied UTF-8 string.
|
||||||
inline static u4 hash_code(const char* string) {
|
inline static u4 hash_code(const char* string) {
|
||||||
return hash_code(string, HASH_MULTIPLIER);
|
return hash_code(string, HASH_MULTIPLIER);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute the Perfect Hashing hash code for the supplied string, starting at seed.
|
// Compute the Perfect Hashing hash code for the supplied string, starting at seed.
|
||||||
static u4 hash_code(const char* string, u4 seed);
|
static s4 hash_code(const char* string, s4 seed);
|
||||||
|
|
||||||
// Test to see if string begins with start. If so returns remaining portion
|
// Match up a string in a perfect hash table. Result still needs validation
|
||||||
// of string. Otherwise, NULL. Used to test sections of a path without
|
// for precise match.
|
||||||
// copying.
|
static s4 find(Endian* endian, const char* name, s4* redirect, u4 length);
|
||||||
|
|
||||||
|
// Test to see if UTF-8 string begins with the start UTF-8 string. If so,
|
||||||
|
// return non-NULL address of remaining portion of string. Otherwise, return
|
||||||
|
// NULL. Used to test sections of a path without copying from image string
|
||||||
|
// table.
|
||||||
static const char* starts_with(const char* string, const char* start);
|
static const char* starts_with(const char* string, const char* start);
|
||||||
|
|
||||||
|
// Test to see if UTF-8 string begins with start char. If so, return non-NULL
|
||||||
|
// address of remaining portion of string. Otherwise, return NULL. Used
|
||||||
|
// to test a character of a path without copying.
|
||||||
|
inline static const char* starts_with(const char* string, const char ch) {
|
||||||
|
return *string == ch ? string + 1 : NULL;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Manage image file location attribute streams. Within an image, a location's
|
// Manage image file location attribute data. Within an image, a location's
|
||||||
// attributes are compressed into a stream of bytes. An attribute stream is
|
// attributes are compressed into a stream of bytes. An attribute stream is
|
||||||
// composed of individual attribute sequences. Each attribute sequence begins with
|
// composed of individual attribute sequences. Each attribute sequence begins with
|
||||||
// a header byte containing the attribute 'kind' (upper 5 bits of header) and the
|
// a header byte containing the attribute 'kind' (upper 5 bits of header) and the
|
||||||
@ -188,7 +215,7 @@ public:
|
|||||||
// stream.
|
// stream.
|
||||||
// - ATTRIBUTE_OFFSET represents the number of bytes from the beginning of the region
|
// - ATTRIBUTE_OFFSET represents the number of bytes from the beginning of the region
|
||||||
// storing the resources. Thus, in an image this represents the number of bytes
|
// storing the resources. Thus, in an image this represents the number of bytes
|
||||||
// after the directory.
|
// after the index.
|
||||||
// - Currently, compressed resources are represented by having a non-zero
|
// - Currently, compressed resources are represented by having a non-zero
|
||||||
// ATTRIBUTE_COMPRESSED value. This represents the number of bytes stored in the
|
// ATTRIBUTE_COMPRESSED value. This represents the number of bytes stored in the
|
||||||
// image, and the value of ATTRIBUTE_UNCOMPRESSED represents number of bytes of the
|
// image, and the value of ATTRIBUTE_UNCOMPRESSED represents number of bytes of the
|
||||||
@ -198,17 +225,19 @@ public:
|
|||||||
// represented differently.
|
// represented differently.
|
||||||
// - Package strings include trailing slash and extensions include prefix period.
|
// - Package strings include trailing slash and extensions include prefix period.
|
||||||
//
|
//
|
||||||
class ImageLocation {
|
class ImageLocation VALUE_OBJ_CLASS_SPEC {
|
||||||
public:
|
public:
|
||||||
// Attribute kind enumeration.
|
enum {
|
||||||
static const u1 ATTRIBUTE_END = 0; // End of attribute stream marker
|
ATTRIBUTE_END, // End of attribute stream marker
|
||||||
static const u1 ATTRIBUTE_BASE = 1; // String table offset of resource path base
|
ATTRIBUTE_MODULE, // String table offset of module name
|
||||||
static const u1 ATTRIBUTE_PARENT = 2; // String table offset of resource path parent
|
ATTRIBUTE_PARENT, // String table offset of resource path parent
|
||||||
static const u1 ATTRIBUTE_EXTENSION = 3; // String table offset of resource path extension
|
ATTRIBUTE_BASE, // String table offset of resource path base
|
||||||
static const u1 ATTRIBUTE_OFFSET = 4; // Container byte offset of resource
|
ATTRIBUTE_EXTENSION, // String table offset of resource path extension
|
||||||
static const u1 ATTRIBUTE_COMPRESSED = 5; // In image byte size of the compressed resource
|
ATTRIBUTE_OFFSET, // Container byte offset of resource
|
||||||
static const u1 ATTRIBUTE_UNCOMPRESSED = 6; // In memory byte size of the uncompressed resource
|
ATTRIBUTE_COMPRESSED, // In image byte size of the compressed resource
|
||||||
static const u1 ATTRIBUTE_COUNT = 7; // Number of attribute kinds
|
ATTRIBUTE_UNCOMPRESSED, // In memory byte size of the uncompressed resource
|
||||||
|
ATTRIBUTE_COUNT // Number of attribute kinds
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Values of inflated attributes.
|
// Values of inflated attributes.
|
||||||
@ -222,30 +251,43 @@ private:
|
|||||||
// Return the attribute kind.
|
// Return the attribute kind.
|
||||||
inline static u1 attribute_kind(u1 data) {
|
inline static u1 attribute_kind(u1 data) {
|
||||||
u1 kind = data >> 3;
|
u1 kind = data >> 3;
|
||||||
assert(kind < ATTRIBUTE_COUNT, "invalid attribute kind");
|
guarantee(kind < ATTRIBUTE_COUNT, "invalid attribute kind");
|
||||||
return kind;
|
return kind;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the attribute length.
|
// Return the attribute length.
|
||||||
inline static u8 attribute_value(u1* data, u1 n) {
|
inline static u8 attribute_value(u1* data, u1 n) {
|
||||||
assert(0 < n && n <= 8, "invalid attribute value length");
|
guarantee(0 < n && n <= 8, "invalid attribute value length");
|
||||||
u8 value = 0;
|
u8 value = 0;
|
||||||
|
|
||||||
// Most significant bytes first.
|
// Most significant bytes first.
|
||||||
for (u1 i = 0; i < n; i++) {
|
for (u1 i = 0; i < n; i++) {
|
||||||
value <<= 8;
|
value <<= 8;
|
||||||
value |= data[i];
|
value |= data[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ImageLocation(u1* data);
|
ImageLocation() {
|
||||||
|
clear_data();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageLocation(u1* data) {
|
||||||
|
clear_data();
|
||||||
|
set_data(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inflates the attribute stream into individual values stored in the long
|
||||||
|
// array _attributes. This allows an attribute value to be quickly accessed by
|
||||||
|
// direct indexing. Unspecified values default to zero.
|
||||||
|
void set_data(u1* data);
|
||||||
|
|
||||||
|
// Zero all attribute values.
|
||||||
|
void clear_data();
|
||||||
|
|
||||||
// Retrieve an attribute value from the inflated array.
|
// Retrieve an attribute value from the inflated array.
|
||||||
inline u8 get_attribute(u1 kind) const {
|
inline u8 get_attribute(u1 kind) const {
|
||||||
assert(ATTRIBUTE_END < kind && kind < ATTRIBUTE_COUNT, "invalid attribute kind");
|
guarantee(ATTRIBUTE_END < kind && kind < ATTRIBUTE_COUNT, "invalid attribute kind");
|
||||||
return _attributes[kind];
|
return _attributes[kind];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,89 +297,306 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Manage the image file.
|
//
|
||||||
class ImageFile: public CHeapObj<mtClass> {
|
// NOTE: needs revision.
|
||||||
private:
|
// Each loader requires set of module meta data to identify which modules and
|
||||||
// Image file marker.
|
// packages are managed by that loader. Currently, there is one image file per
|
||||||
static const u4 IMAGE_MAGIC = 0xCAFEDADA;
|
// builtin loader, so only one module meta data resource per file.
|
||||||
// Image file major version number.
|
//
|
||||||
static const u2 MAJOR_VERSION = 0;
|
// Each element in the module meta data is a native endian 4 byte integer. Note
|
||||||
// Image file minor version number.
|
// that entries with zero offsets for string table entries should be ignored (
|
||||||
static const u2 MINOR_VERSION = 1;
|
// padding for hash table lookup.)
|
||||||
|
//
|
||||||
struct ImageHeader {
|
// Format:
|
||||||
u4 _magic; // Image file marker
|
// Count of package to module entries
|
||||||
u2 _major_version; // Image file major version number
|
// Count of module to package entries
|
||||||
u2 _minor_version; // Image file minor version number
|
// Perfect Hash redirect table[Count of package to module entries]
|
||||||
u4 _location_count; // Number of locations managed in index.
|
// Package to module entries[Count of package to module entries]
|
||||||
u4 _locations_size; // Number of bytes in attribute table.
|
// Offset to package name in string table
|
||||||
u4 _strings_size; // Number of bytes in string table.
|
// Offset to module name in string table
|
||||||
|
// Perfect Hash redirect table[Count of module to package entries]
|
||||||
|
// Module to package entries[Count of module to package entries]
|
||||||
|
// Offset to module name in string table
|
||||||
|
// Count of packages in module
|
||||||
|
// Offset to first package in packages table
|
||||||
|
// Packages[]
|
||||||
|
// Offset to package name in string table
|
||||||
|
//
|
||||||
|
// Manage the image module meta data.
|
||||||
|
class ImageModuleData : public CHeapObj<mtClass> {
|
||||||
|
class Header VALUE_OBJ_CLASS_SPEC {
|
||||||
|
private:
|
||||||
|
u4 _ptm_count; // Count of package to module entries
|
||||||
|
u4 _mtp_count; // Count of module to package entries
|
||||||
|
public:
|
||||||
|
inline u4 ptm_count(Endian* endian) const { return endian->get(_ptm_count); }
|
||||||
|
inline u4 mtp_count(Endian* endian) const { return endian->get(_mtp_count); }
|
||||||
};
|
};
|
||||||
|
|
||||||
char* _name; // Name of image
|
// Hashtable entry
|
||||||
int _fd; // File descriptor
|
class HashData VALUE_OBJ_CLASS_SPEC {
|
||||||
bool _memory_mapped; // Is file memory mapped
|
private:
|
||||||
ImageHeader _header; // Image header
|
u4 _name_offset; // Name offset in string table
|
||||||
u8 _index_size; // Total size of index
|
public:
|
||||||
u1* _index_data; // Raw index data
|
inline s4 name_offset(Endian* endian) const { return endian->get(_name_offset); }
|
||||||
s4* _redirect_table; // Perfect hash redirect table
|
};
|
||||||
u4* _offsets_table; // Location offset table
|
|
||||||
u1* _location_bytes; // Location attributes
|
// Package to module hashtable entry
|
||||||
u1* _string_bytes; // String table
|
class PTMData : public HashData {
|
||||||
|
private:
|
||||||
|
u4 _module_name_offset; // Module name offset in string table
|
||||||
|
public:
|
||||||
|
inline s4 module_name_offset(Endian* endian) const { return endian->get(_module_name_offset); }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Module to package hashtable entry
|
||||||
|
class MTPData : public HashData {
|
||||||
|
private:
|
||||||
|
u4 _package_count; // Number of packages in module
|
||||||
|
u4 _package_offset; // Offset in package list
|
||||||
|
public:
|
||||||
|
inline u4 package_count(Endian* endian) const { return endian->get(_package_count); }
|
||||||
|
inline u4 package_offset(Endian* endian) const { return endian->get(_package_offset); }
|
||||||
|
};
|
||||||
|
|
||||||
|
const ImageFileReader* _image_file; // Source image file
|
||||||
|
Endian* _endian; // Endian handler
|
||||||
|
ImageStrings _strings; // Image file strings
|
||||||
|
u1* _data; // Module data resource data
|
||||||
|
u8 _data_size; // Size of resource data
|
||||||
|
Header* _header; // Module data header
|
||||||
|
s4* _ptm_redirect; // Package to module hashtable redirect
|
||||||
|
PTMData* _ptm_data; // Package to module data
|
||||||
|
s4* _mtp_redirect; // Module to packages hashtable redirect
|
||||||
|
MTPData* _mtp_data; // Module to packages data
|
||||||
|
s4* _mtp_packages; // Package data (name offsets)
|
||||||
|
|
||||||
|
// Return a string from the string table.
|
||||||
|
inline const char* get_string(u4 offset) {
|
||||||
|
return _strings.get(offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline u4 mtp_package(u4 index) {
|
||||||
|
return _endian->get(_mtp_packages[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
ImageModuleData(const ImageFileReader* image_file, const char* module_data_name);
|
||||||
|
~ImageModuleData();
|
||||||
|
|
||||||
|
// Return the name of the module data resource.
|
||||||
|
static void module_data_name(char* buffer, const char* image_file_name);
|
||||||
|
|
||||||
|
// Return the module in which a package resides. Returns NULL if not found.
|
||||||
|
const char* package_to_module(const char* package_name);
|
||||||
|
|
||||||
|
// Returns all the package names in a module. Returns NULL if module not found.
|
||||||
|
GrowableArray<const char*>* module_to_packages(const char* module_name);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Image file header, starting at offset 0.
|
||||||
|
class ImageHeader VALUE_OBJ_CLASS_SPEC {
|
||||||
|
private:
|
||||||
|
u4 _magic; // Image file marker
|
||||||
|
u4 _version; // Image file major version number
|
||||||
|
u4 _flags; // Image file flags
|
||||||
|
u4 _resource_count; // Number of resources in file
|
||||||
|
u4 _table_length; // Number of slots in index tables
|
||||||
|
u4 _locations_size; // Number of bytes in attribute table
|
||||||
|
u4 _strings_size; // Number of bytes in string table
|
||||||
|
|
||||||
|
public:
|
||||||
|
u4 magic() const { return _magic; }
|
||||||
|
u4 magic(Endian* endian) const { return endian->get(_magic); }
|
||||||
|
void set_magic(Endian* endian, u4 magic) { return endian->set(_magic, magic); }
|
||||||
|
|
||||||
|
u4 major_version(Endian* endian) const { return endian->get(_version) >> 16; }
|
||||||
|
u4 minor_version(Endian* endian) const { return endian->get(_version) & 0xFFFF; }
|
||||||
|
void set_version(Endian* endian, u4 major_version, u4 minor_version) {
|
||||||
|
return endian->set(_version, major_version << 16 | minor_version);
|
||||||
|
}
|
||||||
|
|
||||||
|
u4 flags(Endian* endian) const { return endian->get(_flags); }
|
||||||
|
void set_flags(Endian* endian, u4 value) { return endian->set(_flags, value); }
|
||||||
|
|
||||||
|
u4 resource_count(Endian* endian) const { return endian->get(_resource_count); }
|
||||||
|
void set_resource_count(Endian* endian, u4 count) { return endian->set(_resource_count, count); }
|
||||||
|
|
||||||
|
u4 table_length(Endian* endian) const { return endian->get(_table_length); }
|
||||||
|
void set_table_length(Endian* endian, u4 count) { return endian->set(_table_length, count); }
|
||||||
|
|
||||||
|
u4 locations_size(Endian* endian) const { return endian->get(_locations_size); }
|
||||||
|
void set_locations_size(Endian* endian, u4 size) { return endian->set(_locations_size, size); }
|
||||||
|
|
||||||
|
u4 strings_size(Endian* endian) const { return endian->get(_strings_size); }
|
||||||
|
void set_strings_size(Endian* endian, u4 size) { return endian->set(_strings_size, size); }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Max path length limit independent of platform. Windows max path is 1024,
|
||||||
|
// other platforms use 4096. The JCK fails several tests when 1024 is used.
|
||||||
|
#define IMAGE_MAX_PATH 4096
|
||||||
|
|
||||||
|
// Manage the image file.
|
||||||
|
// ImageFileReader manages the content of an image file.
|
||||||
|
// Initially, the header of the image file is read for validation. If valid,
|
||||||
|
// values in the header are used calculate the size of the image index. The
|
||||||
|
// index is then memory mapped to allow load on demand and sharing. The
|
||||||
|
// -XX:+MemoryMapImage flag determines if the entire file is loaded (server use.)
|
||||||
|
// An image can be used by Hotspot and multiple reference points in the JDK, thus
|
||||||
|
// it is desirable to share a reader. To accomodate sharing, a share table is
|
||||||
|
// defined (see ImageFileReaderTable in imageFile.cpp) To track the number of
|
||||||
|
// uses, ImageFileReader keeps a use count (_use). Use is incremented when
|
||||||
|
// 'opened' by reference point and decremented when 'closed'. Use of zero
|
||||||
|
// leads the ImageFileReader to be actually closed and discarded.
|
||||||
|
class ImageFileReader : public CHeapObj<mtClass> {
|
||||||
|
private:
|
||||||
|
// Manage a number of image files such that an image can be shared across
|
||||||
|
// multiple uses (ex. loader.)
|
||||||
|
static GrowableArray<ImageFileReader*>* _reader_table;
|
||||||
|
|
||||||
|
char* _name; // Name of image
|
||||||
|
s4 _use; // Use count
|
||||||
|
int _fd; // File descriptor
|
||||||
|
Endian* _endian; // Endian handler
|
||||||
|
u8 _file_size; // File size in bytes
|
||||||
|
ImageHeader _header; // Image header
|
||||||
|
size_t _index_size; // Total size of index
|
||||||
|
u1* _index_data; // Raw index data
|
||||||
|
s4* _redirect_table; // Perfect hash redirect table
|
||||||
|
u4* _offsets_table; // Location offset table
|
||||||
|
u1* _location_bytes; // Location attributes
|
||||||
|
u1* _string_bytes; // String table
|
||||||
|
|
||||||
|
ImageFileReader(const char* name, bool big_endian);
|
||||||
|
~ImageFileReader();
|
||||||
|
|
||||||
// Compute number of bytes in image file index.
|
// Compute number of bytes in image file index.
|
||||||
inline u8 index_size() {
|
inline u8 index_size() {
|
||||||
return sizeof(ImageHeader) +
|
return sizeof(ImageHeader) +
|
||||||
_header._location_count * sizeof(u4) * 2 +
|
table_length() * sizeof(u4) * 2 + locations_size() + strings_size();
|
||||||
_header._locations_size +
|
|
||||||
_header._strings_size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ImageFile(const char* name);
|
enum {
|
||||||
~ImageFile();
|
// Image file marker.
|
||||||
|
IMAGE_MAGIC = 0xCAFEDADA,
|
||||||
|
// Endian inverted Image file marker.
|
||||||
|
IMAGE_MAGIC_INVERT = 0xDADAFECA,
|
||||||
|
// Image file major version number.
|
||||||
|
MAJOR_VERSION = 1,
|
||||||
|
// Image file minor version number.
|
||||||
|
MINOR_VERSION = 0
|
||||||
|
};
|
||||||
|
|
||||||
// Open image file for access.
|
// Open an image file, reuse structure if file already open.
|
||||||
|
static ImageFileReader* open(const char* name, bool big_endian = Endian::is_big_endian());
|
||||||
|
|
||||||
|
// Close an image file if the file is not in use elsewhere.
|
||||||
|
static void close(ImageFileReader *reader);
|
||||||
|
|
||||||
|
// Return an id for the specifed ImageFileReader.
|
||||||
|
static u8 readerToID(ImageFileReader *reader);
|
||||||
|
|
||||||
|
// Validate the image id.
|
||||||
|
static bool idCheck(u8 id);
|
||||||
|
|
||||||
|
// Return an id for the specifed ImageFileReader.
|
||||||
|
static ImageFileReader* idToReader(u8 id);
|
||||||
|
|
||||||
|
// Open image file for read access.
|
||||||
bool open();
|
bool open();
|
||||||
|
|
||||||
// Close image file.
|
// Close image file.
|
||||||
void close();
|
void close();
|
||||||
|
|
||||||
|
// Read directly from the file.
|
||||||
|
bool read_at(u1* data, u8 size, u8 offset) const;
|
||||||
|
|
||||||
|
inline Endian* endian() const { return _endian; }
|
||||||
|
|
||||||
// Retrieve name of image file.
|
// Retrieve name of image file.
|
||||||
inline const char* name() const {
|
inline const char* name() const {
|
||||||
return _name;
|
return _name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Retrieve size of image file.
|
||||||
|
inline u8 file_size() const {
|
||||||
|
return _file_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return first address of index data.
|
||||||
|
inline u1* get_index_address() const {
|
||||||
|
return _index_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return first address of resource data.
|
||||||
|
inline u1* get_data_address() const {
|
||||||
|
return _index_data + _index_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the size of the index data.
|
||||||
|
size_t get_index_size() const {
|
||||||
|
return _index_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline u4 table_length() const {
|
||||||
|
return _header.table_length(_endian);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline u4 locations_size() const {
|
||||||
|
return _header.locations_size(_endian);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline u4 strings_size()const {
|
||||||
|
return _header.strings_size(_endian);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline u4* offsets_table() const {
|
||||||
|
return _offsets_table;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Increment use count.
|
||||||
|
inline void inc_use() {
|
||||||
|
_use++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decrement use count.
|
||||||
|
inline bool dec_use() {
|
||||||
|
return --_use == 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Return a string table accessor.
|
// Return a string table accessor.
|
||||||
inline const ImageStrings get_strings() const {
|
inline const ImageStrings get_strings() const {
|
||||||
return ImageStrings(_string_bytes, _header._strings_size);
|
return ImageStrings(_string_bytes, _header.strings_size(_endian));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return number of locations in image file index.
|
// Return location attribute stream at offset.
|
||||||
inline u4 get_location_count() const {
|
inline u1* get_location_offset_data(u4 offset) const {
|
||||||
return _header._location_count;
|
guarantee((u4)offset < _header.locations_size(_endian),
|
||||||
}
|
"offset exceeds location attributes size");
|
||||||
|
|
||||||
// Return location attribute stream for location i.
|
|
||||||
inline u1* get_location_data(u4 i) const {
|
|
||||||
u4 offset = _offsets_table[i];
|
|
||||||
|
|
||||||
return offset != 0 ? _location_bytes + offset : NULL;
|
return offset != 0 ? _location_bytes + offset : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the attribute stream for a named resourced.
|
// Return location attribute stream for location i.
|
||||||
u1* find_location_data(const char* path) const;
|
inline u1* get_location_data(u4 index) const {
|
||||||
|
guarantee((u4)index < _header.table_length(_endian),
|
||||||
|
"index exceeds location count");
|
||||||
|
u4 offset = _endian->get(_offsets_table[index]);
|
||||||
|
|
||||||
|
return get_location_offset_data(offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the location attributes associated with the path. Returns true if
|
||||||
|
// the location is found, false otherwise.
|
||||||
|
bool find_location(const char* path, ImageLocation& location) const;
|
||||||
|
|
||||||
|
// Assemble the location path.
|
||||||
|
void location_path(ImageLocation& location, char* path, size_t max) const;
|
||||||
|
|
||||||
// Verify that a found location matches the supplied path.
|
// Verify that a found location matches the supplied path.
|
||||||
bool verify_location(ImageLocation& location, const char* path) const;
|
bool verify_location(ImageLocation& location, const char* path) const;
|
||||||
|
|
||||||
// Return the resource for the supplied location info.
|
// Return the resource for the supplied path.
|
||||||
u1* get_resource(ImageLocation& location) const;
|
void get_resource(ImageLocation& location, u1* uncompressed_data) const;
|
||||||
|
|
||||||
// Return the resource associated with the path else NULL if not found.
|
|
||||||
void get_resource(const char* path, u1*& buffer, u8& size) const;
|
|
||||||
|
|
||||||
// Return an array of packages for a given module
|
|
||||||
GrowableArray<const char*>* packages(const char* name);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SHARE_VM_CLASSFILE_IMAGEFILE_HPP
|
#endif // SHARE_VM_CLASSFILE_IMAGEFILE_HPP
|
||||||
|
@ -57,6 +57,8 @@
|
|||||||
# include "classfile/classFileParser.hpp"
|
# include "classfile/classFileParser.hpp"
|
||||||
# include "classfile/classFileStream.hpp"
|
# include "classfile/classFileStream.hpp"
|
||||||
# include "classfile/classLoader.hpp"
|
# include "classfile/classLoader.hpp"
|
||||||
|
# include "classfile/imageDecompressor.hpp"
|
||||||
|
# include "classfile/imageFile.hpp"
|
||||||
# include "classfile/javaClasses.hpp"
|
# include "classfile/javaClasses.hpp"
|
||||||
# include "classfile/symbolTable.hpp"
|
# include "classfile/symbolTable.hpp"
|
||||||
# include "classfile/systemDictionary.hpp"
|
# include "classfile/systemDictionary.hpp"
|
||||||
@ -229,6 +231,7 @@
|
|||||||
# include "utilities/constantTag.hpp"
|
# include "utilities/constantTag.hpp"
|
||||||
# include "utilities/copy.hpp"
|
# include "utilities/copy.hpp"
|
||||||
# include "utilities/debug.hpp"
|
# include "utilities/debug.hpp"
|
||||||
|
# include "utilities/endian.hpp"
|
||||||
# include "utilities/exceptions.hpp"
|
# include "utilities/exceptions.hpp"
|
||||||
# include "utilities/globalDefinitions.hpp"
|
# include "utilities/globalDefinitions.hpp"
|
||||||
# include "utilities/growableArray.hpp"
|
# include "utilities/growableArray.hpp"
|
||||||
|
@ -24,6 +24,8 @@
|
|||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "classfile/classLoader.hpp"
|
#include "classfile/classLoader.hpp"
|
||||||
|
#include "classfile/imageDecompressor.hpp"
|
||||||
|
#include "classfile/imageFile.hpp"
|
||||||
#include "classfile/javaAssertions.hpp"
|
#include "classfile/javaAssertions.hpp"
|
||||||
#include "classfile/javaClasses.inline.hpp"
|
#include "classfile/javaClasses.inline.hpp"
|
||||||
#include "classfile/stringTable.hpp"
|
#include "classfile/stringTable.hpp"
|
||||||
@ -69,6 +71,7 @@
|
|||||||
#include "utilities/copy.hpp"
|
#include "utilities/copy.hpp"
|
||||||
#include "utilities/defaultStream.hpp"
|
#include "utilities/defaultStream.hpp"
|
||||||
#include "utilities/dtrace.hpp"
|
#include "utilities/dtrace.hpp"
|
||||||
|
#include "utilities/endian.hpp"
|
||||||
#include "utilities/events.hpp"
|
#include "utilities/events.hpp"
|
||||||
#include "utilities/histogram.hpp"
|
#include "utilities/histogram.hpp"
|
||||||
#include "utilities/macros.hpp"
|
#include "utilities/macros.hpp"
|
||||||
@ -3665,3 +3668,244 @@ JVM_ENTRY(void, JVM_GetVersionInfo(JNIEnv* env, jvm_version_info* info, size_t i
|
|||||||
info->is_attachable = AttachListener::is_attach_supported();
|
info->is_attachable = AttachListener::is_attach_supported();
|
||||||
}
|
}
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
|
// jdk.internal.jimage /////////////////////////////////////////////////////////
|
||||||
|
// WARNING: This API is experimental and temporary during JDK 9 development
|
||||||
|
// cycle. It will not be supported in the eventual JDK 9 release.
|
||||||
|
|
||||||
|
// Java entry to open an image file for sharing.
|
||||||
|
// WARNING: This API is experimental and temporary during JDK 9 development
|
||||||
|
// cycle. It will not be supported in the eventual JDK 9 release.
|
||||||
|
JVM_ENTRY(jlong,
|
||||||
|
JVM_ImageOpen(JNIEnv *env, const char *nativePath, jboolean big_endian)) {
|
||||||
|
JVMWrapper("JVM_ImageOpen");
|
||||||
|
// Open image file for reading.
|
||||||
|
ImageFileReader* reader = ImageFileReader::open(nativePath, big_endian != JNI_FALSE);
|
||||||
|
// Return image ID as a jlong.
|
||||||
|
return ImageFileReader::readerToID(reader);
|
||||||
|
}
|
||||||
|
JVM_END
|
||||||
|
|
||||||
|
// Java entry for closing a shared image file.
|
||||||
|
// WARNING: This API is experimental and temporary during JDK 9 development
|
||||||
|
// cycle. It will not be supported in the eventual JDK 9 release.
|
||||||
|
JVM_ENTRY(void,
|
||||||
|
JVM_ImageClose(JNIEnv *env, jlong id)) {
|
||||||
|
JVMWrapper("JVM_ImageClose");
|
||||||
|
// Convert image ID to image reader structure.
|
||||||
|
ImageFileReader* reader = ImageFileReader::idToReader(id);
|
||||||
|
// If valid reader the close.
|
||||||
|
if (reader != NULL) {
|
||||||
|
ImageFileReader::close(reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
JVM_END
|
||||||
|
|
||||||
|
// Java entry for accessing the base address of the image index.
|
||||||
|
// WARNING: This API is experimental and temporary during JDK 9 development
|
||||||
|
// cycle. It will not be supported in the eventual JDK 9 release.
|
||||||
|
JVM_ENTRY(jlong,
|
||||||
|
JVM_ImageGetIndexAddress(JNIEnv *env, jlong id)) {
|
||||||
|
JVMWrapper("JVM_ImageGetIndexAddress");
|
||||||
|
// Convert image ID to image reader structure.
|
||||||
|
ImageFileReader* reader = ImageFileReader::idToReader(id);
|
||||||
|
// If valid reader return index base address (as jlong) else zero.
|
||||||
|
return reader != NULL ? (jlong)reader->get_index_address() : 0L;
|
||||||
|
}
|
||||||
|
JVM_END
|
||||||
|
|
||||||
|
// Java entry for accessing the base address of the image data.
|
||||||
|
// WARNING: This API is experimental and temporary during JDK 9 development
|
||||||
|
// cycle. It will not be supported in the eventual JDK 9 release.
|
||||||
|
JVM_ENTRY(jlong,
|
||||||
|
JVM_ImageGetDataAddress(JNIEnv *env, jlong id)) {
|
||||||
|
JVMWrapper("JVM_ImageGetDataAddress");
|
||||||
|
// Convert image ID to image reader structure.
|
||||||
|
ImageFileReader* reader = ImageFileReader::idToReader(id);
|
||||||
|
// If valid reader return data base address (as jlong) else zero.
|
||||||
|
return MemoryMapImage && reader != NULL ? (jlong)reader->get_data_address() : 0L;
|
||||||
|
}
|
||||||
|
JVM_END
|
||||||
|
|
||||||
|
// Java entry for reading an uncompressed resource from the image.
|
||||||
|
// WARNING: This API is experimental and temporary during JDK 9 development
|
||||||
|
// cycle. It will not be supported in the eventual JDK 9 release.
|
||||||
|
JVM_ENTRY(jboolean,
|
||||||
|
JVM_ImageRead(JNIEnv *env, jlong id, jlong offset,
|
||||||
|
unsigned char* uncompressedAddress, jlong uncompressed_size)) {
|
||||||
|
JVMWrapper("JVM_ImageRead");
|
||||||
|
// Convert image ID to image reader structure.
|
||||||
|
ImageFileReader* reader = ImageFileReader::idToReader(id);\
|
||||||
|
// If not a valid reader the fail the read.
|
||||||
|
if (reader == NULL) return false;
|
||||||
|
// Get the file offset of resource data.
|
||||||
|
u8 file_offset = reader->get_index_size() + offset;
|
||||||
|
// Check validity of arguments.
|
||||||
|
if (offset < 0 ||
|
||||||
|
uncompressed_size < 0 ||
|
||||||
|
file_offset > reader->file_size() - uncompressed_size) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Read file content into buffer.
|
||||||
|
return (jboolean)reader->read_at((u1*)uncompressedAddress, uncompressed_size,
|
||||||
|
file_offset);
|
||||||
|
}
|
||||||
|
JVM_END
|
||||||
|
|
||||||
|
// Java entry for reading a compressed resource from the image.
|
||||||
|
// WARNING: This API is experimental and temporary during JDK 9 development
|
||||||
|
// cycle. It will not be supported in the eventual JDK 9 release.
|
||||||
|
JVM_ENTRY(jboolean,
|
||||||
|
JVM_ImageReadCompressed(JNIEnv *env,
|
||||||
|
jlong id, jlong offset,
|
||||||
|
unsigned char* compressedAddress, jlong compressed_size,
|
||||||
|
unsigned char* uncompressedAddress, jlong uncompressed_size)) {
|
||||||
|
JVMWrapper("JVM_ImageReadCompressed");
|
||||||
|
// Convert image ID to image reader structure.
|
||||||
|
ImageFileReader* reader = ImageFileReader::idToReader(id);
|
||||||
|
// If not a valid reader the fail the read.
|
||||||
|
if (reader == NULL) return false;
|
||||||
|
// Get the file offset of resource data.
|
||||||
|
u8 file_offset = reader->get_index_size() + offset;
|
||||||
|
// Check validity of arguments.
|
||||||
|
if (offset < 0 ||
|
||||||
|
compressed_size < 0 ||
|
||||||
|
uncompressed_size < 0 ||
|
||||||
|
file_offset > reader->file_size() - compressed_size) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read file content into buffer.
|
||||||
|
bool is_read = reader->read_at(compressedAddress, compressed_size,
|
||||||
|
file_offset);
|
||||||
|
// If successfully read then decompress.
|
||||||
|
if (is_read) {
|
||||||
|
const ImageStrings strings = reader->get_strings();
|
||||||
|
ImageDecompressor::decompress_resource(compressedAddress, uncompressedAddress,
|
||||||
|
uncompressed_size, &strings, true);
|
||||||
|
}
|
||||||
|
return (jboolean)is_read;
|
||||||
|
}
|
||||||
|
JVM_END
|
||||||
|
|
||||||
|
// Java entry for retrieving UTF-8 bytes from image string table.
|
||||||
|
// WARNING: This API is experimental and temporary during JDK 9 development
|
||||||
|
// cycle. It will not be supported in the eventual JDK 9 release.
|
||||||
|
JVM_ENTRY(const char*, JVM_ImageGetStringBytes(JNIEnv *env, jlong id, jint offset)) {
|
||||||
|
JVMWrapper("JVM_ImageGetStringBytes");
|
||||||
|
// Convert image ID to image reader structure.
|
||||||
|
ImageFileReader* reader = ImageFileReader::idToReader(id);
|
||||||
|
// Fail if not valid reader.
|
||||||
|
if (reader == NULL) return NULL;
|
||||||
|
// Manage image string table.
|
||||||
|
ImageStrings strings = reader->get_strings();
|
||||||
|
// Retrieve string adrress from table.
|
||||||
|
const char* data = strings.get(offset);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
JVM_END
|
||||||
|
|
||||||
|
// Utility function to copy location information into a jlong array.
|
||||||
|
// WARNING: This function is experimental and temporary during JDK 9 development
|
||||||
|
// cycle. It will not be supported in the eventual JDK 9 release.
|
||||||
|
static void image_expand_location(JNIEnv *env, jlong* rawAttributes, ImageLocation& location) {
|
||||||
|
// Copy attributes from location.
|
||||||
|
for (int kind = ImageLocation::ATTRIBUTE_END + 1;
|
||||||
|
kind < ImageLocation::ATTRIBUTE_COUNT;
|
||||||
|
kind++) {
|
||||||
|
rawAttributes[kind] = location.get_attribute(kind);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Java entry for retrieving location attributes for attribute offset.
|
||||||
|
// WARNING: This API is experimental and temporary during JDK 9 development
|
||||||
|
// cycle. It will not be supported in the eventual JDK 9 release.
|
||||||
|
JVM_ENTRY(jlong*, JVM_ImageGetAttributes(JNIEnv *env, jlong* rawAttributes, jlong id, jint offset)) {
|
||||||
|
JVMWrapper("JVM_ImageGetAttributes");
|
||||||
|
// Convert image ID to image reader structure.
|
||||||
|
ImageFileReader* reader = ImageFileReader::idToReader(id);
|
||||||
|
// Fail if not valid reader.
|
||||||
|
if (reader == NULL) return NULL;
|
||||||
|
// Retrieve first byte address of resource's location attribute stream.
|
||||||
|
u1* data = reader->get_location_offset_data(offset);
|
||||||
|
// Fail if not valid offset.
|
||||||
|
if (data == NULL) return NULL;
|
||||||
|
// Expand stream into array.
|
||||||
|
ImageLocation location(data);
|
||||||
|
image_expand_location(env, rawAttributes, location);
|
||||||
|
return rawAttributes;
|
||||||
|
}
|
||||||
|
JVM_END
|
||||||
|
|
||||||
|
// Java entry for retrieving location attributes count for attribute offset.
|
||||||
|
// WARNING: This API is experimental and temporary during JDK 9 development
|
||||||
|
// cycle. It will not be supported in the eventual JDK 9 release.
|
||||||
|
JVM_ENTRY(jsize, JVM_ImageGetAttributesCount(JNIEnv *env)) {
|
||||||
|
JVMWrapper("JVM_ImageGetAttributesCount");
|
||||||
|
return ImageLocation::ATTRIBUTE_COUNT;
|
||||||
|
}
|
||||||
|
JVM_END
|
||||||
|
|
||||||
|
// Java entry for retrieving location attributes for named resource.
|
||||||
|
// WARNING: This API is experimental and temporary during JDK 9 development
|
||||||
|
// cycle. It will not be supported in the eventual JDK 9 release.
|
||||||
|
JVM_ENTRY(jlong*,
|
||||||
|
JVM_ImageFindAttributes(JNIEnv *env, jlong* rawAttributes, jbyte* rawBytes, jsize size, jlong id)) {
|
||||||
|
JVMWrapper("JVM_ImageFindAttributes");
|
||||||
|
// Mark for temporary buffers.
|
||||||
|
ResourceMark rm;
|
||||||
|
// Convert image ID to image reader structure.
|
||||||
|
ImageFileReader* reader = ImageFileReader::idToReader(id);
|
||||||
|
// Fail if not valid reader.
|
||||||
|
if (reader == NULL) return NULL;
|
||||||
|
// Convert byte array to a cstring.
|
||||||
|
char* path = NEW_RESOURCE_ARRAY(char, size + 1);
|
||||||
|
memcpy(path, rawBytes, size);
|
||||||
|
path[size] = '\0';
|
||||||
|
// Locate resource location data.
|
||||||
|
ImageLocation location;
|
||||||
|
bool found = reader->find_location(path, location);
|
||||||
|
// Resource not found.
|
||||||
|
if (!found) return NULL;
|
||||||
|
// Expand stream into array.
|
||||||
|
image_expand_location(env, rawAttributes, location);
|
||||||
|
return rawAttributes;
|
||||||
|
}
|
||||||
|
JVM_END
|
||||||
|
|
||||||
|
// Java entry for retrieving all the attribute stream offsets from an image.
|
||||||
|
// WARNING: This API is experimental and temporary during JDK 9 development
|
||||||
|
// cycle. It will not be supported in the eventual JDK 9 release.
|
||||||
|
JVM_ENTRY(jint*, JVM_ImageAttributeOffsets(JNIEnv *env, jint* rawOffsets, unsigned int length, jlong id)) {
|
||||||
|
JVMWrapper("JVM_ImageAttributeOffsets");
|
||||||
|
// Convert image ID to image reader structure.
|
||||||
|
ImageFileReader* reader = ImageFileReader::idToReader(id);
|
||||||
|
// Fail if not valid reader.
|
||||||
|
if (reader == NULL) return NULL;
|
||||||
|
// Determine endian for reader.
|
||||||
|
Endian* endian = reader->endian();
|
||||||
|
// Get base address of attribute stream offsets table.
|
||||||
|
u4* offsets_table = reader->offsets_table();
|
||||||
|
// Allocate int array result.
|
||||||
|
// Copy values to result (converting endian.)
|
||||||
|
for (u4 i = 0; i < length; i++) {
|
||||||
|
rawOffsets[i] = endian->get(offsets_table[i]);
|
||||||
|
}
|
||||||
|
return rawOffsets;
|
||||||
|
}
|
||||||
|
JVM_END
|
||||||
|
|
||||||
|
// Java entry for retrieving all the attribute stream offsets length from an image.
|
||||||
|
// WARNING: This API is experimental and temporary during JDK 9 development
|
||||||
|
// cycle. It will not be supported in the eventual JDK 9 release.
|
||||||
|
JVM_ENTRY(unsigned int, JVM_ImageAttributeOffsetsLength(JNIEnv *env, jlong id)) {
|
||||||
|
JVMWrapper("JVM_ImageAttributeOffsetsLength");
|
||||||
|
// Convert image ID to image reader structure.
|
||||||
|
ImageFileReader* reader = ImageFileReader::idToReader(id);
|
||||||
|
// Fail if not valid reader.
|
||||||
|
if (reader == NULL) return 0;
|
||||||
|
// Get perfect hash table length.
|
||||||
|
u4 length = reader->table_length();
|
||||||
|
return (jint) length;
|
||||||
|
}
|
||||||
|
JVM_END
|
||||||
|
@ -571,6 +571,52 @@ JVM_AssertionStatusDirectives(JNIEnv *env, jclass unused);
|
|||||||
JNIEXPORT jboolean JNICALL
|
JNIEXPORT jboolean JNICALL
|
||||||
JVM_SupportsCX8(void);
|
JVM_SupportsCX8(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* jdk.internal.jimage
|
||||||
|
* WARNING: This API is experimental and temporary during JDK 9 development
|
||||||
|
* cycle. It will not be supported in the eventual JDK 9 release.
|
||||||
|
*/
|
||||||
|
|
||||||
|
JNIEXPORT jlong JNICALL
|
||||||
|
JVM_ImageOpen(JNIEnv *env, const char *nativePath, jboolean big_endian);
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL
|
||||||
|
JVM_ImageClose(JNIEnv *env, jlong id);
|
||||||
|
|
||||||
|
JNIEXPORT jlong JNICALL
|
||||||
|
JVM_ImageGetIndexAddress(JNIEnv *env, jlong id);
|
||||||
|
|
||||||
|
JNIEXPORT jlong JNICALL
|
||||||
|
JVM_ImageGetDataAddress(JNIEnv *env,jlong id);
|
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL
|
||||||
|
JVM_ImageRead(JNIEnv *env, jlong id, jlong offset,
|
||||||
|
unsigned char* uncompressedAddress, jlong uncompressed_size);
|
||||||
|
|
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL
|
||||||
|
JVM_ImageReadCompressed(JNIEnv *env, jlong id, jlong offset,
|
||||||
|
unsigned char* compressedBuffer, jlong compressed_size,
|
||||||
|
unsigned char* uncompressedBuffer, jlong uncompressed_size);
|
||||||
|
|
||||||
|
JNIEXPORT const char* JNICALL
|
||||||
|
JVM_ImageGetStringBytes(JNIEnv *env, jlong id, jint offset);
|
||||||
|
|
||||||
|
JNIEXPORT jlong* JNICALL
|
||||||
|
JVM_ImageGetAttributes(JNIEnv *env, jlong* rawAttributes, jlong id, jint offset);
|
||||||
|
|
||||||
|
JNIEXPORT jsize JNICALL
|
||||||
|
JVM_ImageGetAttributesCount(JNIEnv *env);
|
||||||
|
|
||||||
|
JNIEXPORT jlong* JNICALL
|
||||||
|
JVM_ImageFindAttributes(JNIEnv *env, jlong* rawAttributes, jbyte* rawBytes, jsize size, jlong id);
|
||||||
|
|
||||||
|
JNIEXPORT jint* JNICALL
|
||||||
|
JVM_ImageAttributeOffsets(JNIEnv *env, jint* rawOffsets, unsigned int length, jlong id);
|
||||||
|
|
||||||
|
JNIEXPORT unsigned int JNICALL
|
||||||
|
JVM_ImageAttributeOffsetsLength(JNIEnv *env, jlong id);
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
PART 2: Support for the Verifier and Class File Format Checker
|
PART 2: Support for the Verifier and Class File Format Checker
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include <new>
|
#include <new>
|
||||||
|
|
||||||
#include "classfile/classLoaderData.hpp"
|
#include "classfile/classLoaderData.hpp"
|
||||||
|
#include "classfile/imageFile.hpp"
|
||||||
#include "classfile/stringTable.hpp"
|
#include "classfile/stringTable.hpp"
|
||||||
#include "code/codeCache.hpp"
|
#include "code/codeCache.hpp"
|
||||||
#include "jvmtifiles/jvmtiEnv.hpp"
|
#include "jvmtifiles/jvmtiEnv.hpp"
|
||||||
@ -1125,6 +1126,132 @@ WB_ENTRY(jlong, WB_MetaspaceCapacityUntilGC(JNIEnv* env, jobject wb))
|
|||||||
return (jlong) MetaspaceGC::capacity_until_GC();
|
return (jlong) MetaspaceGC::capacity_until_GC();
|
||||||
WB_END
|
WB_END
|
||||||
|
|
||||||
|
WB_ENTRY(jboolean, WB_ReadImageFile(JNIEnv* env, jobject wb, jstring imagefile))
|
||||||
|
const char* filename = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(imagefile));
|
||||||
|
return ImageFileReader::open(filename) != NULL;
|
||||||
|
WB_END
|
||||||
|
|
||||||
|
WB_ENTRY(jlong, WB_imageOpenImage(JNIEnv *env, jobject wb, jstring path, jboolean big_endian))
|
||||||
|
ThreadToNativeFromVM ttn(thread);
|
||||||
|
const char *nativePath = env->GetStringUTFChars(path, NULL);
|
||||||
|
jlong ret = JVM_ImageOpen(env, nativePath, big_endian);
|
||||||
|
|
||||||
|
env->ReleaseStringUTFChars(path, nativePath);
|
||||||
|
return ret;
|
||||||
|
WB_END
|
||||||
|
|
||||||
|
WB_ENTRY(void, WB_imageCloseImage(JNIEnv *env, jobject wb, jlong id))
|
||||||
|
ThreadToNativeFromVM ttn(thread);
|
||||||
|
JVM_ImageClose(env, id);
|
||||||
|
WB_END
|
||||||
|
|
||||||
|
WB_ENTRY(jlong, WB_imageGetIndexAddress(JNIEnv *env, jobject wb, jlong id))
|
||||||
|
ThreadToNativeFromVM ttn(thread);
|
||||||
|
return JVM_ImageGetIndexAddress(env, id);
|
||||||
|
WB_END
|
||||||
|
|
||||||
|
WB_ENTRY(jlong, WB_imageGetDataAddress(JNIEnv *env, jobject wb, jlong id))
|
||||||
|
ThreadToNativeFromVM ttn(thread);
|
||||||
|
return JVM_ImageGetDataAddress(env, id);
|
||||||
|
WB_END
|
||||||
|
|
||||||
|
WB_ENTRY(jboolean, WB_imageRead(JNIEnv *env, jobject wb, jlong id, jlong offset, jobject uncompressedBuffer, jlong uncompressed_size))
|
||||||
|
ThreadToNativeFromVM ttn(thread);
|
||||||
|
if (uncompressedBuffer == NULL) {
|
||||||
|
return JNI_FALSE;
|
||||||
|
}
|
||||||
|
unsigned char* uncompressedAddress =
|
||||||
|
(unsigned char*) env->GetDirectBufferAddress(uncompressedBuffer);
|
||||||
|
return JVM_ImageRead(env, id, offset, uncompressedAddress, uncompressed_size);
|
||||||
|
WB_END
|
||||||
|
|
||||||
|
WB_ENTRY(jboolean, WB_imageReadCompressed(JNIEnv *env, jobject wb, jlong id, jlong offset, jobject compressedBuffer, jlong compressed_size, jobject uncompressedBuffer, jlong uncompressed_size))
|
||||||
|
ThreadToNativeFromVM ttn(thread);
|
||||||
|
if (uncompressedBuffer == NULL || compressedBuffer == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Get address of read direct buffer.
|
||||||
|
unsigned char* compressedAddress =
|
||||||
|
(unsigned char*) env->GetDirectBufferAddress(compressedBuffer);
|
||||||
|
// Get address of decompression direct buffer.
|
||||||
|
unsigned char* uncompressedAddress =
|
||||||
|
(unsigned char*) env->GetDirectBufferAddress(uncompressedBuffer);
|
||||||
|
return JVM_ImageReadCompressed(env, id, offset, compressedAddress, compressed_size, uncompressedAddress, uncompressed_size);
|
||||||
|
WB_END
|
||||||
|
|
||||||
|
WB_ENTRY(jbyteArray, WB_imageGetStringBytes(JNIEnv *env, jobject wb, jlong id, jlong offset))
|
||||||
|
ThreadToNativeFromVM ttn(thread);
|
||||||
|
const char* data = JVM_ImageGetStringBytes(env, id, offset);
|
||||||
|
// Determine String length.
|
||||||
|
size_t size = strlen(data);
|
||||||
|
// Allocate byte array.
|
||||||
|
jbyteArray byteArray = env->NewByteArray((jsize) size);
|
||||||
|
// Get array base address.
|
||||||
|
jbyte* rawBytes = env->GetByteArrayElements(byteArray, NULL);
|
||||||
|
// Copy bytes from image string table.
|
||||||
|
memcpy(rawBytes, data, size);
|
||||||
|
// Release byte array base address.
|
||||||
|
env->ReleaseByteArrayElements(byteArray, rawBytes, 0);
|
||||||
|
return byteArray;
|
||||||
|
WB_END
|
||||||
|
|
||||||
|
WB_ENTRY(jlong, WB_imageGetStringsSize(JNIEnv *env, jobject wb, jlong id))
|
||||||
|
ImageFileReader* reader = ImageFileReader::idToReader(id);
|
||||||
|
return reader? reader->strings_size() : 0L;
|
||||||
|
WB_END
|
||||||
|
|
||||||
|
WB_ENTRY(jlongArray, WB_imageGetAttributes(JNIEnv *env, jobject wb, jlong id, jint offset))
|
||||||
|
ThreadToNativeFromVM ttn(thread);
|
||||||
|
// Allocate a jlong large enough for all location attributes.
|
||||||
|
jlongArray attributes = env->NewLongArray(JVM_ImageGetAttributesCount(env));
|
||||||
|
// Get base address for jlong array.
|
||||||
|
jlong* rawAttributes = env->GetLongArrayElements(attributes, NULL);
|
||||||
|
jlong* ret = JVM_ImageGetAttributes(env, rawAttributes, id, offset);
|
||||||
|
// Release jlong array base address.
|
||||||
|
env->ReleaseLongArrayElements(attributes, rawAttributes, 0);
|
||||||
|
return ret == NULL ? NULL : attributes;
|
||||||
|
WB_END
|
||||||
|
|
||||||
|
WB_ENTRY(jlongArray, WB_imageFindAttributes(JNIEnv *env, jobject wb, jlong id, jbyteArray utf8))
|
||||||
|
ThreadToNativeFromVM ttn(thread);
|
||||||
|
// Allocate a jlong large enough for all location attributes.
|
||||||
|
jlongArray attributes = env->NewLongArray(JVM_ImageGetAttributesCount(env));
|
||||||
|
// Get base address for jlong array.
|
||||||
|
jlong* rawAttributes = env->GetLongArrayElements(attributes, NULL);
|
||||||
|
jsize size = env->GetArrayLength(utf8);
|
||||||
|
jbyte* rawBytes = env->GetByteArrayElements(utf8, NULL);
|
||||||
|
jlong* ret = JVM_ImageFindAttributes(env, rawAttributes, rawBytes, size, id);
|
||||||
|
env->ReleaseByteArrayElements(utf8, rawBytes, 0);
|
||||||
|
env->ReleaseLongArrayElements(attributes, rawAttributes, 0);
|
||||||
|
return ret == NULL ? NULL : attributes;
|
||||||
|
WB_END
|
||||||
|
|
||||||
|
WB_ENTRY(jintArray, WB_imageAttributeOffsets(JNIEnv *env, jobject wb, jlong id))
|
||||||
|
ThreadToNativeFromVM ttn(thread);
|
||||||
|
unsigned int length = JVM_ImageAttributeOffsetsLength(env, id);
|
||||||
|
if (length == 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
jintArray offsets = env->NewIntArray(length);
|
||||||
|
// Get base address of result.
|
||||||
|
jint* rawOffsets = env->GetIntArrayElements(offsets, NULL);
|
||||||
|
jint* ret = JVM_ImageAttributeOffsets(env, rawOffsets, length, id);
|
||||||
|
// Release result base address.
|
||||||
|
env->ReleaseIntArrayElements(offsets, rawOffsets, 0);
|
||||||
|
return ret == NULL ? NULL : offsets;
|
||||||
|
WB_END
|
||||||
|
|
||||||
|
WB_ENTRY(jint, WB_imageGetIntAtAddress(JNIEnv *env, jobject wb, jlong address, jint offset, jboolean big_endian))
|
||||||
|
unsigned char* arr = (unsigned char*) address + offset;
|
||||||
|
jint uraw;
|
||||||
|
if (big_endian) {
|
||||||
|
uraw = arr[0] << 24 | arr[1]<<16 | (arr[2]<<8) | arr[3];
|
||||||
|
} else {
|
||||||
|
uraw = arr[0] | arr[1]<<8 | (arr[2]<<16) | arr[3]<<24;
|
||||||
|
}
|
||||||
|
return uraw;
|
||||||
|
WB_END
|
||||||
|
|
||||||
WB_ENTRY(void, WB_AssertMatchingSafepointCalls(JNIEnv* env, jobject o, jboolean mutexSafepointValue, jboolean attemptedNoSafepointValue))
|
WB_ENTRY(void, WB_AssertMatchingSafepointCalls(JNIEnv* env, jobject o, jboolean mutexSafepointValue, jboolean attemptedNoSafepointValue))
|
||||||
Monitor::SafepointCheckRequired sfpt_check_required = mutexSafepointValue ?
|
Monitor::SafepointCheckRequired sfpt_check_required = mutexSafepointValue ?
|
||||||
Monitor::_safepoint_check_always :
|
Monitor::_safepoint_check_always :
|
||||||
@ -1428,8 +1555,23 @@ static JNINativeMethod methods[] = {
|
|||||||
{CC"getCodeBlob", CC"(J)[Ljava/lang/Object;",(void*)&WB_GetCodeBlob },
|
{CC"getCodeBlob", CC"(J)[Ljava/lang/Object;",(void*)&WB_GetCodeBlob },
|
||||||
{CC"getThreadStackSize", CC"()J", (void*)&WB_GetThreadStackSize },
|
{CC"getThreadStackSize", CC"()J", (void*)&WB_GetThreadStackSize },
|
||||||
{CC"getThreadRemainingStackSize", CC"()J", (void*)&WB_GetThreadRemainingStackSize },
|
{CC"getThreadRemainingStackSize", CC"()J", (void*)&WB_GetThreadRemainingStackSize },
|
||||||
|
{CC"readImageFile", CC"(Ljava/lang/String;)Z", (void*)&WB_ReadImageFile },
|
||||||
|
{CC"imageOpenImage", CC"(Ljava/lang/String;Z)J",(void*)&WB_imageOpenImage },
|
||||||
|
{CC"imageCloseImage", CC"(J)V", (void*)&WB_imageCloseImage },
|
||||||
|
{CC"imageGetIndexAddress",CC"(J)J", (void*)&WB_imageGetIndexAddress},
|
||||||
|
{CC"imageGetDataAddress",CC"(J)J", (void*)&WB_imageGetDataAddress},
|
||||||
|
{CC"imageRead", CC"(JJLjava/nio/ByteBuffer;J)Z",
|
||||||
|
(void*)&WB_imageRead },
|
||||||
|
{CC"imageReadCompressed",CC"(JJLjava/nio/ByteBuffer;JLjava/nio/ByteBuffer;J)Z",
|
||||||
|
(void*)&WB_imageReadCompressed},
|
||||||
|
{CC"imageGetStringBytes",CC"(JI)[B", (void*)&WB_imageGetStringBytes},
|
||||||
|
{CC"imageGetStringsSize",CC"(J)J", (void*)&WB_imageGetStringsSize},
|
||||||
|
{CC"imageGetAttributes", CC"(JI)[J", (void*)&WB_imageGetAttributes},
|
||||||
|
{CC"imageFindAttributes",CC"(J[B)[J", (void*)&WB_imageFindAttributes},
|
||||||
|
{CC"imageAttributeOffsets",CC"(J)[I", (void*)&WB_imageAttributeOffsets},
|
||||||
|
{CC"imageGetIntAtAddress",CC"(JIZ)I", (void*)&WB_imageGetIntAtAddress},
|
||||||
{CC"assertMatchingSafepointCalls", CC"(ZZ)V", (void*)&WB_AssertMatchingSafepointCalls },
|
{CC"assertMatchingSafepointCalls", CC"(ZZ)V", (void*)&WB_AssertMatchingSafepointCalls },
|
||||||
{CC"isMonitorInflated0", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsMonitorInflated },
|
{CC"isMonitorInflated0", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsMonitorInflated },
|
||||||
{CC"forceSafepoint", CC"()V", (void*)&WB_ForceSafepoint },
|
{CC"forceSafepoint", CC"()V", (void*)&WB_ForceSafepoint },
|
||||||
{CC"getMethodBooleanOption",
|
{CC"getMethodBooleanOption",
|
||||||
CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/Boolean;",
|
CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/Boolean;",
|
||||||
|
@ -1582,6 +1582,9 @@ void Arguments::set_ergonomics_flags() {
|
|||||||
// in vm_version initialization code.
|
// in vm_version initialization code.
|
||||||
#endif // _LP64
|
#endif // _LP64
|
||||||
#endif // !ZERO
|
#endif // !ZERO
|
||||||
|
|
||||||
|
// Set up runtime image flags.
|
||||||
|
set_runtime_image_flags();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Arguments::set_parallel_gc_flags() {
|
void Arguments::set_parallel_gc_flags() {
|
||||||
@ -1837,6 +1840,16 @@ void Arguments::set_heap_size() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set up runtime image flags
|
||||||
|
void Arguments::set_runtime_image_flags() {
|
||||||
|
#ifdef _LP64
|
||||||
|
// Memory map image file by default on 64 bit machines.
|
||||||
|
if (FLAG_IS_DEFAULT(MemoryMapImage)) {
|
||||||
|
FLAG_SET_ERGO(bool, MemoryMapImage, true);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// This must be called after ergonomics.
|
// This must be called after ergonomics.
|
||||||
void Arguments::set_bytecode_flags() {
|
void Arguments::set_bytecode_flags() {
|
||||||
if (!RewriteBytecodes) {
|
if (!RewriteBytecodes) {
|
||||||
|
@ -347,6 +347,8 @@ class Arguments : AllStatic {
|
|||||||
static julong limit_by_allocatable_memory(julong size);
|
static julong limit_by_allocatable_memory(julong size);
|
||||||
// Setup heap size
|
// Setup heap size
|
||||||
static void set_heap_size();
|
static void set_heap_size();
|
||||||
|
// Set up runtime image flags
|
||||||
|
static void set_runtime_image_flags();
|
||||||
// Based on automatic selection criteria, should the
|
// Based on automatic selection criteria, should the
|
||||||
// low pause collector be used.
|
// low pause collector be used.
|
||||||
static bool should_auto_select_low_pause_collector();
|
static bool should_auto_select_low_pause_collector();
|
||||||
|
@ -1093,6 +1093,9 @@ public:
|
|||||||
product(bool, AlwaysRestoreFPU, false, \
|
product(bool, AlwaysRestoreFPU, false, \
|
||||||
"Restore the FPU control word after every JNI call (expensive)") \
|
"Restore the FPU control word after every JNI call (expensive)") \
|
||||||
\
|
\
|
||||||
|
product(bool, MemoryMapImage, false, \
|
||||||
|
"Memory map entire runtime image") \
|
||||||
|
\
|
||||||
diagnostic(bool, PrintCompilation2, false, \
|
diagnostic(bool, PrintCompilation2, false, \
|
||||||
"Print additional statistics per compilation") \
|
"Print additional statistics per compilation") \
|
||||||
\
|
\
|
||||||
|
@ -82,6 +82,7 @@ void stubRoutines_init2(); // note: StubRoutines need 2-phase init
|
|||||||
// during VM shutdown
|
// during VM shutdown
|
||||||
void perfMemory_exit();
|
void perfMemory_exit();
|
||||||
void ostream_exit();
|
void ostream_exit();
|
||||||
|
bool image_decompressor_init();
|
||||||
|
|
||||||
void vm_init_globals() {
|
void vm_init_globals() {
|
||||||
check_ThreadShadow();
|
check_ThreadShadow();
|
||||||
@ -115,6 +116,9 @@ jint init_globals() {
|
|||||||
templateTable_init();
|
templateTable_init();
|
||||||
InterfaceSupport_init();
|
InterfaceSupport_init();
|
||||||
SharedRuntime::generate_stubs();
|
SharedRuntime::generate_stubs();
|
||||||
|
if (!image_decompressor_init()) {
|
||||||
|
return JNI_ERR;
|
||||||
|
}
|
||||||
universe2_init(); // dependent on codeCache_init and stubRoutines_init1
|
universe2_init(); // dependent on codeCache_init and stubRoutines_init1
|
||||||
referenceProcessor_init();
|
referenceProcessor_init();
|
||||||
jni_handles_init();
|
jni_handles_init();
|
||||||
|
@ -100,6 +100,8 @@ Mutex* ProfilePrint_lock = NULL;
|
|||||||
Mutex* ExceptionCache_lock = NULL;
|
Mutex* ExceptionCache_lock = NULL;
|
||||||
Monitor* ObjAllocPost_lock = NULL;
|
Monitor* ObjAllocPost_lock = NULL;
|
||||||
Mutex* OsrList_lock = NULL;
|
Mutex* OsrList_lock = NULL;
|
||||||
|
Mutex* ImageFileReaderTable_lock = NULL;
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
Mutex* FullGCALot_lock = NULL;
|
Mutex* FullGCALot_lock = NULL;
|
||||||
#endif
|
#endif
|
||||||
@ -227,6 +229,7 @@ void mutex_init() {
|
|||||||
def(ProfilePrint_lock , Mutex , leaf, false, Monitor::_safepoint_check_always); // serial profile printing
|
def(ProfilePrint_lock , Mutex , leaf, false, Monitor::_safepoint_check_always); // serial profile printing
|
||||||
def(ExceptionCache_lock , Mutex , leaf, false, Monitor::_safepoint_check_always); // serial profile printing
|
def(ExceptionCache_lock , Mutex , leaf, false, Monitor::_safepoint_check_always); // serial profile printing
|
||||||
def(OsrList_lock , Mutex , leaf, true, Monitor::_safepoint_check_never);
|
def(OsrList_lock , Mutex , leaf, true, Monitor::_safepoint_check_never);
|
||||||
|
def(ImageFileReaderTable_lock , Mutex , nonleaf, false, Monitor::_safepoint_check_always); // synchronize image readers open/close
|
||||||
def(Debug1_lock , Mutex , leaf, true, Monitor::_safepoint_check_never);
|
def(Debug1_lock , Mutex , leaf, true, Monitor::_safepoint_check_never);
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
def(FullGCALot_lock , Mutex , leaf, false, Monitor::_safepoint_check_always); // a lock to make FullGCALot MT safe
|
def(FullGCALot_lock , Mutex , leaf, false, Monitor::_safepoint_check_always); // a lock to make FullGCALot MT safe
|
||||||
|
@ -102,6 +102,7 @@ extern Monitor* ProfileVM_lock; // a lock used for profiling th
|
|||||||
extern Mutex* ProfilePrint_lock; // a lock used to serialize the printing of profiles
|
extern Mutex* ProfilePrint_lock; // a lock used to serialize the printing of profiles
|
||||||
extern Mutex* ExceptionCache_lock; // a lock used to synchronize exception cache updates
|
extern Mutex* ExceptionCache_lock; // a lock used to synchronize exception cache updates
|
||||||
extern Mutex* OsrList_lock; // a lock used to serialize access to OSR queues
|
extern Mutex* OsrList_lock; // a lock used to serialize access to OSR queues
|
||||||
|
extern Mutex* ImageFileReaderTable_lock; // a lock used to synchronize image readers open/close
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
extern Mutex* FullGCALot_lock; // a lock to make FullGCALot MT safe
|
extern Mutex* FullGCALot_lock; // a lock to make FullGCALot MT safe
|
||||||
|
@ -1237,7 +1237,7 @@ bool os::set_boot_path(char fileSep, char pathSep) {
|
|||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
// modular image if bootmodules.jimage exists
|
// modular image if bootmodules.jimage exists
|
||||||
char* jimage = format_boot_path("%/lib/modules/bootmodules.jimage", home, home_len, fileSep, pathSep);
|
char* jimage = format_boot_path("%/lib/modules/" BOOT_IMAGE_NAME, home, home_len, fileSep, pathSep);
|
||||||
if (jimage == NULL) return false;
|
if (jimage == NULL) return false;
|
||||||
bool has_jimage = (os::stat(jimage, &st) == 0);
|
bool has_jimage = (os::stat(jimage, &st) == 0);
|
||||||
if (has_jimage) {
|
if (has_jimage) {
|
||||||
|
97
hotspot/src/share/vm/utilities/endian.cpp
Normal file
97
hotspot/src/share/vm/utilities/endian.cpp
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "precompiled.hpp"
|
||||||
|
#include "utilities/endian.hpp"
|
||||||
|
#include "utilities/bytes.hpp"
|
||||||
|
|
||||||
|
#ifndef bswap_16
|
||||||
|
extern "C" inline u2 bswap_16(u2 x) {
|
||||||
|
return ((x & 0xFF) << 8) |
|
||||||
|
((x >> 8) & 0xFF);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef bswap_32
|
||||||
|
extern "C" inline u4 bswap_32(u4 x) {
|
||||||
|
return ((x & 0xFF) << 24) |
|
||||||
|
((x & 0xFF00) << 8) |
|
||||||
|
((x >> 8) & 0xFF00) |
|
||||||
|
((x >> 24) & 0xFF);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef bswap_64
|
||||||
|
extern "C" inline u8 bswap_64(u8 x) {
|
||||||
|
return (u8)bswap_32((u4)x) << 32 |
|
||||||
|
(u8)bswap_32((u4)(x >> 32));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
u2 NativeEndian::get(u2 x) { return x; }
|
||||||
|
u4 NativeEndian::get(u4 x) { return x; }
|
||||||
|
u8 NativeEndian::get(u8 x) { return x; }
|
||||||
|
s2 NativeEndian::get(s2 x) { return x; }
|
||||||
|
s4 NativeEndian::get(s4 x) { return x; }
|
||||||
|
s8 NativeEndian::get(s8 x) { return x; }
|
||||||
|
|
||||||
|
void NativeEndian::set(u2& x, u2 y) { x = y; }
|
||||||
|
void NativeEndian::set(u4& x, u4 y) { x = y; }
|
||||||
|
void NativeEndian::set(u8& x, u8 y) { x = y; }
|
||||||
|
void NativeEndian::set(s2& x, s2 y) { x = y; }
|
||||||
|
void NativeEndian::set(s4& x, s4 y) { x = y; }
|
||||||
|
void NativeEndian::set(s8& x, s8 y) { x = y; }
|
||||||
|
|
||||||
|
NativeEndian NativeEndian::_native;
|
||||||
|
|
||||||
|
u2 SwappingEndian::get(u2 x) { return bswap_16(x); }
|
||||||
|
u4 SwappingEndian::get(u4 x) { return bswap_32(x); }
|
||||||
|
u8 SwappingEndian::get(u8 x) { return bswap_64(x); }
|
||||||
|
s2 SwappingEndian::get(s2 x) { return bswap_16(x); }
|
||||||
|
s4 SwappingEndian::get(s4 x) { return bswap_32(x); }
|
||||||
|
s8 SwappingEndian::get(s8 x) { return bswap_64(x); }
|
||||||
|
|
||||||
|
void SwappingEndian::set(u2& x, u2 y) { x = bswap_16(y); }
|
||||||
|
void SwappingEndian::set(u4& x, u4 y) { x = bswap_32(y); }
|
||||||
|
void SwappingEndian::set(u8& x, u8 y) { x = bswap_64(y); }
|
||||||
|
void SwappingEndian::set(s2& x, s2 y) { x = bswap_16(y); }
|
||||||
|
void SwappingEndian::set(s4& x, s4 y) { x = bswap_32(y); }
|
||||||
|
void SwappingEndian::set(s8& x, s8 y) { x = bswap_64(y); }
|
||||||
|
|
||||||
|
SwappingEndian SwappingEndian::_swapping;
|
||||||
|
|
||||||
|
Endian* Endian::get_handler(bool big_endian) {
|
||||||
|
// If requesting little endian on a little endian machine or
|
||||||
|
// big endian on a big endian machine use native handler
|
||||||
|
if (big_endian == is_big_endian()) {
|
||||||
|
return NativeEndian::get_native();
|
||||||
|
} else {
|
||||||
|
// Use swapping handler.
|
||||||
|
return SwappingEndian::get_swapping();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Endian* Endian::get_native_handler() {
|
||||||
|
return NativeEndian::get_native();
|
||||||
|
}
|
119
hotspot/src/share/vm/utilities/endian.hpp
Normal file
119
hotspot/src/share/vm/utilities/endian.hpp
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SHARE_VM_UTILITIES_ENDIAN_HPP
|
||||||
|
#define SHARE_VM_UTILITIES_ENDIAN_HPP
|
||||||
|
|
||||||
|
#include "utilities/globalDefinitions.hpp"
|
||||||
|
|
||||||
|
// Selectable endian handling. Endian handlers are used when accessing values
|
||||||
|
// that are of unknown (until runtime) endian. The only requirement of the values
|
||||||
|
// accessed are that they are aligned to proper size boundaries (no misalignment.)
|
||||||
|
// To select an endian handler, one should call Endian::get_handler(big_endian);
|
||||||
|
// Where big_endian is true if big endian is required and false otherwise. The
|
||||||
|
// native endian handler can be fetched with Endian::get_native_handler();
|
||||||
|
// To retrieve a value using the approprate endian, use one of the overloaded
|
||||||
|
// calls to get. To set a value, then use one of the overloaded set calls.
|
||||||
|
// Ex.
|
||||||
|
// s4 value; // Imported value;
|
||||||
|
// ...
|
||||||
|
// Endian* endian = Endian::get_handler(true); // Use big endian
|
||||||
|
// s4 corrected = endian->get(value);
|
||||||
|
// endian->set(value, 1);
|
||||||
|
//
|
||||||
|
class Endian {
|
||||||
|
public:
|
||||||
|
virtual u2 get(u2 x) = 0;
|
||||||
|
virtual u4 get(u4 x) = 0;
|
||||||
|
virtual u8 get(u8 x) = 0;
|
||||||
|
virtual s2 get(s2 x) = 0;
|
||||||
|
virtual s4 get(s4 x) = 0;
|
||||||
|
virtual s8 get(s8 x) = 0;
|
||||||
|
|
||||||
|
virtual void set(u2& x, u2 y) = 0;
|
||||||
|
virtual void set(u4& x, u4 y) = 0;
|
||||||
|
virtual void set(u8& x, u8 y) = 0;
|
||||||
|
virtual void set(s2& x, s2 y) = 0;
|
||||||
|
virtual void set(s4& x, s4 y) = 0;
|
||||||
|
virtual void set(s8& x, s8 y) = 0;
|
||||||
|
|
||||||
|
// Quick little endian test.
|
||||||
|
static bool is_little_endian() { u4 x = 1; return *(u1 *)&x != 0; }
|
||||||
|
|
||||||
|
// Quick big endian test.
|
||||||
|
static bool is_big_endian() { return !is_little_endian(); }
|
||||||
|
|
||||||
|
// Select an appropriate endian handler.
|
||||||
|
static Endian* get_handler(bool big_endian);
|
||||||
|
|
||||||
|
// Return the native endian handler.
|
||||||
|
static Endian* get_native_handler();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Normal endian handling.
|
||||||
|
class NativeEndian : public Endian {
|
||||||
|
private:
|
||||||
|
static NativeEndian _native;
|
||||||
|
|
||||||
|
public:
|
||||||
|
u2 get(u2 x);
|
||||||
|
u4 get(u4 x);
|
||||||
|
u8 get(u8 x);
|
||||||
|
s2 get(s2 x);
|
||||||
|
s4 get(s4 x);
|
||||||
|
s8 get(s8 x);
|
||||||
|
|
||||||
|
void set(u2& x, u2 y);
|
||||||
|
void set(u4& x, u4 y);
|
||||||
|
void set(u8& x, u8 y);
|
||||||
|
void set(s2& x, s2 y);
|
||||||
|
void set(s4& x, s4 y);
|
||||||
|
void set(s8& x, s8 y);
|
||||||
|
|
||||||
|
static Endian* get_native() { return &_native; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Swapping endian handling.
|
||||||
|
class SwappingEndian : public Endian {
|
||||||
|
private:
|
||||||
|
static SwappingEndian _swapping;
|
||||||
|
|
||||||
|
public:
|
||||||
|
u2 get(u2 x);
|
||||||
|
u4 get(u4 x);
|
||||||
|
u8 get(u8 x);
|
||||||
|
s2 get(s2 x);
|
||||||
|
s4 get(s4 x);
|
||||||
|
s8 get(s8 x);
|
||||||
|
|
||||||
|
void set(u2& x, u2 y);
|
||||||
|
void set(u4& x, u4 y);
|
||||||
|
void set(u8& x, u8 y);
|
||||||
|
void set(s2& x, s2 y);
|
||||||
|
void set(s4& x, s4 y);
|
||||||
|
void set(s8& x, s8 y);
|
||||||
|
|
||||||
|
static Endian* get_swapping() { return &_swapping; }
|
||||||
|
};
|
||||||
|
#endif // SHARE_VM_UTILITIES_ENDIAN_HPP
|
@ -31,6 +31,7 @@
|
|||||||
* java.management
|
* java.management
|
||||||
* @build TestPromotionToSurvivor
|
* @build TestPromotionToSurvivor
|
||||||
* SurvivorAlignmentTestMain AlignmentHelper
|
* SurvivorAlignmentTestMain AlignmentHelper
|
||||||
|
* @ignore 8129886
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
|
@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Retrieves the array of offsets once with MemoryMapImage enabled once disabled.
|
||||||
|
* @test ImageAttributeOffsetsTest
|
||||||
|
* @summary Unit test for JVM_ImageAttributeOffsets() method
|
||||||
|
* @library /testlibrary /../../test/lib
|
||||||
|
* @build ImageAttributeOffsetsTest
|
||||||
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+MemoryMapImage ImageAttributeOffsetsTest
|
||||||
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:-MemoryMapImage ImageAttributeOffsetsTest
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import sun.hotspot.WhiteBox;
|
||||||
|
import static jdk.test.lib.Asserts.*;
|
||||||
|
|
||||||
|
public class ImageAttributeOffsetsTest {
|
||||||
|
|
||||||
|
public static final WhiteBox wb = WhiteBox.getWhiteBox();
|
||||||
|
|
||||||
|
public static void main(String... args) throws Exception {
|
||||||
|
String javaHome = System.getProperty("java.home");
|
||||||
|
String imageFile = javaHome + File.separator + "lib" + File.separator
|
||||||
|
+ "modules" + File.separator + "bootmodules.jimage";
|
||||||
|
|
||||||
|
if (!(new File(imageFile)).exists()) {
|
||||||
|
System.out.printf("Test skipped.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean bigEndian = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN;
|
||||||
|
long id = wb.imageOpenImage(imageFile, bigEndian);
|
||||||
|
boolean passed = true;
|
||||||
|
// Get offsets
|
||||||
|
int[] array = wb.imageAttributeOffsets(id);
|
||||||
|
assertNotNull(array, "Could not retrieve offsets of array");
|
||||||
|
|
||||||
|
wb.imageCloseImage(id);
|
||||||
|
}
|
||||||
|
}
|
68
hotspot/test/runtime/modules/ImageFile/ImageCloseTest.java
Normal file
68
hotspot/test/runtime/modules/ImageFile/ImageCloseTest.java
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test closing image opened multiple time. Test closing mutiple time an image.
|
||||||
|
* @test ImageCloseTest
|
||||||
|
* @summary Unit test for JVM_ImageClose() method
|
||||||
|
* @library /testlibrary /../../test/lib
|
||||||
|
* @build ImageCloseTest
|
||||||
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ImageCloseTest
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import sun.hotspot.WhiteBox;
|
||||||
|
|
||||||
|
public class ImageCloseTest {
|
||||||
|
|
||||||
|
public static final WhiteBox wb = WhiteBox.getWhiteBox();
|
||||||
|
|
||||||
|
public static void main(String... args) throws Exception {
|
||||||
|
String javaHome = System.getProperty("java.home");
|
||||||
|
String imageFile = javaHome + File.separator + "lib" + File.separator
|
||||||
|
+ "modules" + File.separator + "bootmodules.jimage";
|
||||||
|
|
||||||
|
if (!(new File(imageFile)).exists()) {
|
||||||
|
System.out.printf("Test skipped.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean bigEndian = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN;
|
||||||
|
long id = 0;
|
||||||
|
|
||||||
|
// too many opens
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
id = wb.imageOpenImage(imageFile, bigEndian);
|
||||||
|
}
|
||||||
|
wb.imageCloseImage(id);
|
||||||
|
|
||||||
|
// too many closes
|
||||||
|
id = wb.imageOpenImage(imageFile, bigEndian);
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
wb.imageCloseImage(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
126
hotspot/test/runtime/modules/ImageFile/ImageFileHeaderTest.java
Normal file
126
hotspot/test/runtime/modules/ImageFile/ImageFileHeaderTest.java
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test that opening image containing wrong headers fails.
|
||||||
|
* @test ImageFileHeaderTest
|
||||||
|
* @library /testlibrary /../../test/lib
|
||||||
|
* @build ImageFileHeaderTest
|
||||||
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ImageFileHeaderTest
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.nio.*;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import sun.hotspot.WhiteBox;
|
||||||
|
import static jdk.test.lib.Asserts.*;
|
||||||
|
|
||||||
|
public class ImageFileHeaderTest {
|
||||||
|
|
||||||
|
public static final int MAGIC = 0xCAFEDADA;
|
||||||
|
public static final short MAJOR = 0;
|
||||||
|
public static final short MINOR = 1;
|
||||||
|
|
||||||
|
public static final WhiteBox wb = WhiteBox.getWhiteBox();
|
||||||
|
public static ByteBuffer buf;
|
||||||
|
|
||||||
|
public static void main(String... args) throws Exception {
|
||||||
|
|
||||||
|
ByteOrder endian = getEndian();
|
||||||
|
|
||||||
|
// Try to read a non-existing file
|
||||||
|
assertFalse(wb.readImageFile("bogus"));
|
||||||
|
|
||||||
|
// Incomplete header, only include the correct magic
|
||||||
|
buf = ByteBuffer.allocate(100);
|
||||||
|
buf.order(endian);
|
||||||
|
buf.putInt(MAGIC);
|
||||||
|
assertFalse(testImageFile("invalidheader.jimage"));
|
||||||
|
|
||||||
|
// Build a complete header but reverse the endian
|
||||||
|
buf = ByteBuffer.allocate(100);
|
||||||
|
buf.order(endian == ByteOrder.LITTLE_ENDIAN ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
|
||||||
|
buf.putInt(MAGIC);
|
||||||
|
buf.putShort(MAJOR);
|
||||||
|
buf.putShort(MINOR);
|
||||||
|
assertFalse(testImageFile("wrongendian.jimage"));
|
||||||
|
|
||||||
|
// Use the wrong magic
|
||||||
|
buf = ByteBuffer.allocate(100);
|
||||||
|
buf.order(endian);
|
||||||
|
buf.putInt(0xBEEFCACE);
|
||||||
|
buf.putShort(MAJOR);
|
||||||
|
buf.putShort(MINOR);
|
||||||
|
assertFalse(testImageFile("wrongmagic.jimage"));
|
||||||
|
|
||||||
|
// Wrong major version (current + 1)
|
||||||
|
buf = ByteBuffer.allocate(100);
|
||||||
|
buf.order(endian);
|
||||||
|
buf.putInt(MAGIC);
|
||||||
|
buf.putShort((short)(MAJOR + 1));
|
||||||
|
buf.putShort((short)MINOR);
|
||||||
|
assertFalse(testImageFile("wrongmajorversion.jimage"));
|
||||||
|
|
||||||
|
// Wrong major version (negative)
|
||||||
|
buf = ByteBuffer.allocate(100);
|
||||||
|
buf.order(endian);
|
||||||
|
buf.putInt(MAGIC);
|
||||||
|
buf.putShort((short) -17);
|
||||||
|
buf.putShort((short)MINOR);
|
||||||
|
assertFalse(testImageFile("negativemajorversion.jimage"));
|
||||||
|
|
||||||
|
// Wrong minor version (current + 1)
|
||||||
|
buf = ByteBuffer.allocate(100);
|
||||||
|
buf.order(endian);
|
||||||
|
buf.putInt(MAGIC);
|
||||||
|
buf.putShort((short)MAJOR);
|
||||||
|
buf.putShort((short)(MINOR + 1));
|
||||||
|
assertFalse(testImageFile("wrongminorversion.jimage"));
|
||||||
|
|
||||||
|
// Wrong minor version (negative)
|
||||||
|
buf = ByteBuffer.allocate(100);
|
||||||
|
buf.order(endian);
|
||||||
|
buf.putInt(MAGIC);
|
||||||
|
buf.putShort((short)MAJOR);
|
||||||
|
buf.putShort((short) -17);
|
||||||
|
assertFalse(testImageFile("negativeminorversion.jimage"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean testImageFile(String filename) throws Exception {
|
||||||
|
Files.write(Paths.get(filename), buf.array());
|
||||||
|
System.out.println("Calling ReadImageFile on " + filename);
|
||||||
|
return wb.readImageFile(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ByteOrder getEndian() {
|
||||||
|
String endian = System.getProperty("sun.cpu.endian");
|
||||||
|
if (endian.equalsIgnoreCase("little")) {
|
||||||
|
return ByteOrder.LITTLE_ENDIAN;
|
||||||
|
} else if (endian.equalsIgnoreCase("big")) {
|
||||||
|
return ByteOrder.BIG_ENDIAN;
|
||||||
|
}
|
||||||
|
throw new RuntimeException("Unexpected sun.cpu.endian value: " + endian);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find the attributes of existing and invalid classes.
|
||||||
|
* @test ImageFindAttributesTest
|
||||||
|
* @summary Unit test for JVM_ImageFindAttributes() method
|
||||||
|
* @library /testlibrary /../../test/lib
|
||||||
|
* @build ImageFindAttributesTest
|
||||||
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ImageFindAttributesTest
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import sun.hotspot.WhiteBox;
|
||||||
|
import static jdk.test.lib.Asserts.*;
|
||||||
|
|
||||||
|
public class ImageFindAttributesTest {
|
||||||
|
|
||||||
|
public static final WhiteBox wb = WhiteBox.getWhiteBox();
|
||||||
|
|
||||||
|
public static void main(String... args) throws Exception {
|
||||||
|
String javaHome = System.getProperty("java.home");
|
||||||
|
String imageFile = javaHome + File.separator + "lib" + File.separator
|
||||||
|
+ "modules" + File.separator + "bootmodules.jimage";
|
||||||
|
|
||||||
|
if (!(new File(imageFile)).exists()) {
|
||||||
|
System.out.printf("Test skipped.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean bigEndian = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN;
|
||||||
|
long id = wb.imageOpenImage(imageFile, bigEndian);
|
||||||
|
|
||||||
|
// class resource
|
||||||
|
String className = "/java.base/java/lang/String.class";
|
||||||
|
long[] longArr = wb.imageFindAttributes(id, className.getBytes());
|
||||||
|
|
||||||
|
assertNotNull(longArr, "Could not retrieve attributes of class " + className);
|
||||||
|
|
||||||
|
// non-existent resource
|
||||||
|
String neClassName = "/java.base/java/lang/NonExistentClass.class";
|
||||||
|
longArr = wb.imageFindAttributes(id, neClassName.getBytes());
|
||||||
|
|
||||||
|
assertNull(longArr, "Failed. Returned not null for non-existent " + neClassName);
|
||||||
|
|
||||||
|
// garbage byte array
|
||||||
|
byte[] buf = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||||
|
longArr = wb.imageFindAttributes(id, buf);
|
||||||
|
|
||||||
|
assertNull(longArr, "Found attributes for garbage class");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,128 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test getting all attributes,
|
||||||
|
* @test ImageGetAttributesTest
|
||||||
|
* @summary Unit test for JVM_ImageGetAttributes() method
|
||||||
|
* @library /testlibrary /../../test/lib
|
||||||
|
* @build LocationConstants ImageGetAttributesTest
|
||||||
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ImageGetAttributesTest
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import sun.hotspot.WhiteBox;
|
||||||
|
import static jdk.test.lib.Asserts.*;
|
||||||
|
|
||||||
|
public class ImageGetAttributesTest implements LocationConstants {
|
||||||
|
|
||||||
|
public static final WhiteBox wb = WhiteBox.getWhiteBox();
|
||||||
|
|
||||||
|
public static void main(String... args) throws Exception {
|
||||||
|
String javaHome = System.getProperty("java.home");
|
||||||
|
String imageFile = javaHome + File.separator + "lib" + File.separator
|
||||||
|
+ "modules" + File.separator + "bootmodules.jimage";
|
||||||
|
|
||||||
|
if (!(new File(imageFile)).exists()) {
|
||||||
|
System.out.printf("Test skipped.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
testImageGetAttributes(imageFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testImageGetAttributes(String imageFile) {
|
||||||
|
|
||||||
|
boolean bigEndian = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN;
|
||||||
|
long id = wb.imageOpenImage(imageFile, bigEndian);
|
||||||
|
try {
|
||||||
|
long stringsSize = wb.imageGetStringsSize(id);
|
||||||
|
assertNE(stringsSize, 0, "strings size is 0");
|
||||||
|
|
||||||
|
int[] array = wb.imageAttributeOffsets(id);
|
||||||
|
assertNotNull(array, "Could not retrieve offsets of array");
|
||||||
|
|
||||||
|
// Get non-null attributes
|
||||||
|
boolean attFound = false;
|
||||||
|
int[] idx = {-1, -1, -1};
|
||||||
|
// first non-null attribute
|
||||||
|
for (int i = 0; i < array.length; i++) {
|
||||||
|
if (array[i] != 0) {
|
||||||
|
attFound = true;
|
||||||
|
idx[0] = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// middle non-null attribute
|
||||||
|
for (int i = array.length / 2; i < array.length; i++) {
|
||||||
|
if (array[i] != 0) {
|
||||||
|
attFound = true;
|
||||||
|
idx[1] = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// last non-null attribute
|
||||||
|
for (int i = array.length - 1; i >= 0; i--) {
|
||||||
|
if (array[i] != 0) {
|
||||||
|
attFound = true;
|
||||||
|
idx[2] = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assertTrue(attFound, "Failed. No non-null offset attributes");
|
||||||
|
// test cases above
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
if (idx[i] != -1) {
|
||||||
|
long[] attrs = wb.imageGetAttributes(id, (int) array[idx[i]]);
|
||||||
|
long module = attrs[LOCATION_ATTRIBUTE_MODULE];
|
||||||
|
long parent = attrs[LOCATION_ATTRIBUTE_PARENT];
|
||||||
|
long base = attrs[LOCATION_ATTRIBUTE_BASE];
|
||||||
|
long ext = attrs[LOCATION_ATTRIBUTE_EXTENSION];
|
||||||
|
|
||||||
|
if ((module >= 0) && (module < stringsSize)
|
||||||
|
&& (parent >= 0) && (parent < stringsSize)
|
||||||
|
&& (base != 0)
|
||||||
|
&& (ext >= 0) && (ext < stringsSize)) {
|
||||||
|
} else {
|
||||||
|
System.out.printf("Failed. Read attribute offset %d (position %d) but wrong offsets\n",
|
||||||
|
array[idx[i]], idx[i]);
|
||||||
|
System.out.printf(" offsets: module = %d parent = %d base = %d extention = %d\n",
|
||||||
|
module, parent, base, ext);
|
||||||
|
throw new RuntimeException("Read attribute offset error");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
System.out.printf("Failed. Could not read attribute offset %d (position %d)\n",
|
||||||
|
array[idx[i]], idx[i]);
|
||||||
|
throw new RuntimeException("Read attribute offset error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
wb.imageCloseImage(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test accessing the data address of a jimage. This only makes sense when the
|
||||||
|
* entire jimage is mapped into memory.
|
||||||
|
* @test ImageGetDataAddressTest
|
||||||
|
* @summary Unit test for JVM_ImageGetDataAddress() method
|
||||||
|
* @library /testlibrary /../../test/lib
|
||||||
|
* @build ImageGetDataAddressTest
|
||||||
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+MemoryMapImage ImageGetDataAddressTest +
|
||||||
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:-MemoryMapImage ImageGetDataAddressTest -
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import sun.hotspot.WhiteBox;
|
||||||
|
import static jdk.test.lib.Asserts.*;
|
||||||
|
|
||||||
|
public class ImageGetDataAddressTest {
|
||||||
|
|
||||||
|
public static final WhiteBox wb = WhiteBox.getWhiteBox();
|
||||||
|
|
||||||
|
public static void main(String... args) throws Exception {
|
||||||
|
String javaHome = System.getProperty("java.home");
|
||||||
|
String imageFile = javaHome + File.separator + "lib" + File.separator
|
||||||
|
+ "modules" + File.separator + "bootmodules.jimage";
|
||||||
|
|
||||||
|
if (!(new File(imageFile)).exists()) {
|
||||||
|
System.out.printf("Test skipped.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isMMap = args[0].equals("+");
|
||||||
|
|
||||||
|
boolean bigEndian = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN;
|
||||||
|
long id = wb.imageOpenImage(imageFile, bigEndian);
|
||||||
|
|
||||||
|
// get data for valid id
|
||||||
|
long dataAddr = wb.imageGetDataAddress(id);
|
||||||
|
assertFalse((dataAddr == 0) && isMMap, "Failed. Data address is " + dataAddr + " for valid id\n");
|
||||||
|
|
||||||
|
// get data for invalid id == 0
|
||||||
|
dataAddr = wb.imageGetDataAddress(0);
|
||||||
|
assertTrue(dataAddr == 0, "Failed. Data address is " + dataAddr + " for zero id\n");
|
||||||
|
|
||||||
|
wb.imageCloseImage(id);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test the address of the jimage index.
|
||||||
|
* @test ImageGetIndexAddressTest
|
||||||
|
* @summary Unit test for JVM_ImageGetIndexAddress() method
|
||||||
|
* @library /testlibrary /../../test/lib
|
||||||
|
* @build ImageGetIndexAddressTest
|
||||||
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ImageGetIndexAddressTest
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import sun.hotspot.WhiteBox;
|
||||||
|
import static jdk.test.lib.Asserts.*;
|
||||||
|
|
||||||
|
public class ImageGetIndexAddressTest {
|
||||||
|
|
||||||
|
public static final WhiteBox wb = WhiteBox.getWhiteBox();
|
||||||
|
|
||||||
|
public static void main(String... args) throws Exception {
|
||||||
|
String javaHome = System.getProperty("java.home");
|
||||||
|
String imageFile = javaHome + File.separator + "lib" + File.separator
|
||||||
|
+ "modules" + File.separator + "bootmodules.jimage";
|
||||||
|
|
||||||
|
if (!(new File(imageFile)).exists()) {
|
||||||
|
System.out.printf("Test skipped.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean bigEndian = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN;
|
||||||
|
long id = wb.imageOpenImage(imageFile, bigEndian);
|
||||||
|
|
||||||
|
// get index for valid id
|
||||||
|
long indexAddr = wb.imageGetIndexAddress(id);
|
||||||
|
assertFalse(indexAddr == 0, "Failed. Index address is zero for valid id");
|
||||||
|
|
||||||
|
// get index for invalid id == 0
|
||||||
|
indexAddr = wb.imageGetIndexAddress(0);
|
||||||
|
assertTrue(indexAddr == 0, "Failed. Index address is" + indexAddr + " for zero id\n");
|
||||||
|
|
||||||
|
wb.imageCloseImage(id);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test that the string referenced by an attribute is retrieved.
|
||||||
|
* @test ImageGetStringBytesTest
|
||||||
|
* @summary Unit test for JVM_ImageGetStringBytes() method
|
||||||
|
* @library /testlibrary /../../test/lib
|
||||||
|
* @build LocationConstants ImageGetStringBytesTest
|
||||||
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ImageGetStringBytesTest
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import sun.hotspot.WhiteBox;
|
||||||
|
import static jdk.test.lib.Asserts.*;
|
||||||
|
|
||||||
|
public class ImageGetStringBytesTest implements LocationConstants {
|
||||||
|
|
||||||
|
public static final WhiteBox wb = WhiteBox.getWhiteBox();
|
||||||
|
|
||||||
|
public static void main(String... args) throws Exception {
|
||||||
|
String javaHome = System.getProperty("java.home");
|
||||||
|
String imageFile = javaHome + File.separator + "lib" + File.separator
|
||||||
|
+ "modules" + File.separator + "bootmodules.jimage";
|
||||||
|
|
||||||
|
if (!(new File(imageFile)).exists()) {
|
||||||
|
System.out.printf("Test skipped.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean bigEndian = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN;
|
||||||
|
long id = wb.imageOpenImage(imageFile, bigEndian);
|
||||||
|
|
||||||
|
String className = "/java.base/java/lang/String.class";
|
||||||
|
long[] offsetArr = wb.imageFindAttributes(id, className.getBytes());
|
||||||
|
|
||||||
|
// Module
|
||||||
|
assertTrue(checkAttribute(id, offsetArr, LOCATION_ATTRIBUTE_MODULE, "Module"));
|
||||||
|
|
||||||
|
// Parent
|
||||||
|
assertTrue(checkAttribute(id, offsetArr, LOCATION_ATTRIBUTE_PARENT, "Parent"));
|
||||||
|
|
||||||
|
// Base
|
||||||
|
assertTrue(checkAttribute(id, offsetArr, LOCATION_ATTRIBUTE_BASE, "Base"));
|
||||||
|
|
||||||
|
// Extension
|
||||||
|
assertTrue(checkAttribute(id, offsetArr, LOCATION_ATTRIBUTE_EXTENSION, "Extension"));
|
||||||
|
|
||||||
|
wb.imageCloseImage(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean checkAttribute(long id, long[] offsetArr, int attrId, String attrName) {
|
||||||
|
long offset = offsetArr[attrId];
|
||||||
|
return wb.imageGetStringBytes(id, (int) offset) != null;
|
||||||
|
}
|
||||||
|
}
|
84
hotspot/test/runtime/modules/ImageFile/ImageOpenTest.java
Normal file
84
hotspot/test/runtime/modules/ImageFile/ImageOpenTest.java
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test image opening/closing
|
||||||
|
* @test ImageOpenTest
|
||||||
|
* @summary Unit test for JVM_ImageOpen() method
|
||||||
|
* @library /testlibrary /../../test/lib
|
||||||
|
* @build ImageOpenTest
|
||||||
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ImageOpenTest
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import sun.hotspot.WhiteBox;
|
||||||
|
import static jdk.test.lib.Asserts.*;
|
||||||
|
|
||||||
|
public class ImageOpenTest {
|
||||||
|
|
||||||
|
public static final WhiteBox wb = WhiteBox.getWhiteBox();
|
||||||
|
|
||||||
|
public static void main(String... args) throws Exception {
|
||||||
|
String javaHome = System.getProperty("java.home");
|
||||||
|
String nonexistentImageFile = javaHome + "/lib/modules/nonexistent.jimage";
|
||||||
|
String bootmodulesImageFile = javaHome + File.separator + "lib" + File.separator
|
||||||
|
+ "modules" + File.separator + "bootmodules.jimage";
|
||||||
|
|
||||||
|
if (!(new File(bootmodulesImageFile)).exists()) {
|
||||||
|
System.out.printf("Test skipped.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean bigEndian = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN;
|
||||||
|
|
||||||
|
// open nonexistent image
|
||||||
|
long id = wb.imageOpenImage(nonexistentImageFile, bigEndian);
|
||||||
|
assertTrue(id == 0L, "Failed. Get id " + id + "instead of 0 on opening nonexistent file\n");
|
||||||
|
wb.imageCloseImage(id);
|
||||||
|
|
||||||
|
// open bootmodules image
|
||||||
|
id = wb.imageOpenImage(bootmodulesImageFile, bigEndian);
|
||||||
|
assertFalse(id == 0, "Failed. Get id 0 on opening bootmodules.jimage");
|
||||||
|
wb.imageCloseImage(id);
|
||||||
|
|
||||||
|
// non-native endian
|
||||||
|
id = wb.imageOpenImage(bootmodulesImageFile, !bigEndian);
|
||||||
|
assertFalse(id == 0, "Failed. Get id 0 on opening bootmodules.jimage with non-native endian");
|
||||||
|
wb.imageCloseImage(id);
|
||||||
|
|
||||||
|
//
|
||||||
|
// open several times
|
||||||
|
//
|
||||||
|
id = wb.imageOpenImage(bootmodulesImageFile, bigEndian);
|
||||||
|
long id1 = wb.imageOpenImage(bootmodulesImageFile, bigEndian);
|
||||||
|
long id2 = wb.imageOpenImage(bootmodulesImageFile, bigEndian);
|
||||||
|
assertTrue((id == id1) && (id == id2), "Failed. Open thee times with ids " + id + " " + id1 + " " + id1);
|
||||||
|
|
||||||
|
wb.imageCloseImage(id);
|
||||||
|
wb.imageCloseImage(id1);
|
||||||
|
wb.imageCloseImage(id2);
|
||||||
|
}
|
||||||
|
}
|
97
hotspot/test/runtime/modules/ImageFile/ImageReadTest.java
Normal file
97
hotspot/test/runtime/modules/ImageFile/ImageReadTest.java
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test reading resource content.
|
||||||
|
* @test ImageReadTest
|
||||||
|
* @summary Unit test for JVM_ImageRead() method
|
||||||
|
* @library /testlibrary /../../test/lib
|
||||||
|
* @build LocationConstants ImageReadTest
|
||||||
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+MemoryMapImage ImageReadTest +
|
||||||
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:-MemoryMapImage ImageReadTest -
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import sun.hotspot.WhiteBox;
|
||||||
|
import static jdk.test.lib.Asserts.*;
|
||||||
|
|
||||||
|
public class ImageReadTest implements LocationConstants {
|
||||||
|
|
||||||
|
public static final WhiteBox wb = WhiteBox.getWhiteBox();
|
||||||
|
|
||||||
|
public static void main(String... args) throws Exception {
|
||||||
|
String javaHome = System.getProperty("java.home");
|
||||||
|
String imageFile = javaHome + File.separator + "lib"
|
||||||
|
+ File.separator + "modules" + File.separator
|
||||||
|
+ "bootmodules.jimage";
|
||||||
|
|
||||||
|
if (!(new File(imageFile)).exists()) {
|
||||||
|
System.out.printf("Test skipped.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isMMap = args[0].equals("+");
|
||||||
|
|
||||||
|
long id = wb.imageOpenImage(imageFile, isMMap);
|
||||||
|
|
||||||
|
final String mm = isMMap ? "-XX:+MemoryMapImage" : "-XX:-MemoryMapImage";
|
||||||
|
final int magic = 0xCAFEBABE;
|
||||||
|
|
||||||
|
String className = "/java.base/java/lang/String.class";
|
||||||
|
long[] offsetArr = wb.imageFindAttributes(id, className.getBytes());
|
||||||
|
long offset = offsetArr[LOCATION_ATTRIBUTE_OFFSET];
|
||||||
|
long size = offsetArr[LOCATION_ATTRIBUTE_UNCOMPRESSED];
|
||||||
|
|
||||||
|
// positive: read
|
||||||
|
ByteBuffer buf = ByteBuffer.allocateDirect((int) size);
|
||||||
|
assertTrue(wb.imageRead(id, offset, buf, size), "Failed. Read operation returned false, should be true");
|
||||||
|
int m = buf.getInt();
|
||||||
|
assertTrue(m == magic, "Failed. Read operation returned true but wrong magic = " + magic);
|
||||||
|
|
||||||
|
// positive: mmap
|
||||||
|
if (isMMap) {
|
||||||
|
long dataAddr = wb.imageGetDataAddress(id);
|
||||||
|
assertFalse(dataAddr == 0L, "Failed. Did not obtain data address on mmapped test");
|
||||||
|
int data = wb.imageGetIntAtAddress(dataAddr, (int) offset, true);
|
||||||
|
assertTrue(data == magic, "Failed. MMap operation returned true but wrong magic = " + data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// negative: wrong offset
|
||||||
|
boolean success = wb.imageRead(id, -100, buf, size);
|
||||||
|
assertFalse(success, "Failed. Read operation (wrong offset): returned true");
|
||||||
|
|
||||||
|
// negative: too big offset
|
||||||
|
long filesize = new File(imageFile).length();
|
||||||
|
success = wb.imageRead(id, filesize + 1, buf, size);
|
||||||
|
assertFalse(success, "Failed. Read operation (offset > file size) returned true");
|
||||||
|
|
||||||
|
// negative: negative size
|
||||||
|
success = wb.imageRead(id, offset, buf, -100);
|
||||||
|
assertFalse(success, "Failed. Read operation (negative size) returned true");
|
||||||
|
|
||||||
|
wb.imageCloseImage(id);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public interface LocationConstants {
|
||||||
|
// keep this in sync with enum in ImageLocation C++ class in the
|
||||||
|
// hotspot's C++ header file imageFile.hpp
|
||||||
|
public static final int LOCATION_ATTRIBUTE_END = 0; // End of attribute stream marker
|
||||||
|
public static final int LOCATION_ATTRIBUTE_MODULE = 1; // String table offset of module name
|
||||||
|
public static final int LOCATION_ATTRIBUTE_PARENT = 2; // String table offset of resource path parent
|
||||||
|
public static final int LOCATION_ATTRIBUTE_BASE = 3; // String table offset of resource path base
|
||||||
|
public static final int LOCATION_ATTRIBUTE_EXTENSION = 4; // String table offset of resource path extension
|
||||||
|
public static final int LOCATION_ATTRIBUTE_OFFSET = 5; // Container byte offset of resource
|
||||||
|
public static final int LOCATION_ATTRIBUTE_COMPRESSED = 6; // In image byte size of the compressed resource
|
||||||
|
public static final int LOCATION_ATTRIBUTE_UNCOMPRESSED = 7; // In memory byte size of the uncompressed resource
|
||||||
|
public static final int LOCATION_ATTRIBUTE_COUNT = 8; // Number of attribute kinds
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user