8188791: Move AppCDS from closed repo to open repo

Co-authored-by: Mikhailo Seledtsov <mikhailo.seledtsov@oracle.com>
Co-authored-by: Calvin Cheung <calvin.cheung@oracle.com>
Reviewed-by: dsamersoff, simonis, minqi
This commit is contained in:
Jiangli Zhou 2017-11-27 20:21:34 -08:00 committed by Ioi Lam
parent 570a828dfc
commit 61e736cbae
265 changed files with 31331 additions and 134 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2017, 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
@ -23,13 +23,32 @@
*/
#include "precompiled.hpp"
#include "jvm.h"
#include "jimage.hpp"
#include "classfile/classListParser.hpp"
#include "runtime/os.hpp"
#include "runtime/java.hpp"
#include "classfile/classLoaderExt.hpp"
#include "classfile/sharedClassUtil.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/systemDictionaryShared.hpp"
#include "memory/metaspaceShared.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/fieldType.hpp"
#include "runtime/javaCalls.hpp"
#include "utilities/defaultStream.hpp"
#include "utilities/hashtable.inline.hpp"
#include "utilities/macros.hpp"
ClassListParser* ClassListParser::_instance = NULL;
ClassListParser::ClassListParser(const char* file) {
assert(_instance == NULL, "must be singleton");
_instance = this;
_classlist_file = file;
_file = fopen(file, "r");
_line_no = 0;
_interfaces = new (ResourceObj::C_HEAP, mtClass) GrowableArray<int>(10, true);
if (_file == NULL) {
char errmsg[JVM_MAXPATHLEN];
os::lasterror(errmsg, JVM_MAXPATHLEN);
@ -41,6 +60,7 @@ ClassListParser::~ClassListParser() {
if (_file) {
fclose(_file);
}
_instance = NULL;
}
bool ClassListParser::parse_one_line() {
@ -48,10 +68,10 @@ bool ClassListParser::parse_one_line() {
if (fgets(_line, sizeof(_line), _file) == NULL) {
return false;
}
int line_len = (int)strlen(_line);
if (line_len > _max_allowed_line_len) {
tty->print_cr("input line too long (must be no longer than %d chars)", _max_allowed_line_len);
vm_exit_during_initialization("Loading classlist failed");
++ _line_no;
_line_len = (int)strlen(_line);
if (_line_len > _max_allowed_line_len) {
error("input line too long (must be no longer than %d chars)", _max_allowed_line_len);
}
if (*_line == '#') { // comment
continue;
@ -59,8 +79,378 @@ bool ClassListParser::parse_one_line() {
break;
}
// Remove trailing \r\n
_line[strcspn(_line, "\r\n")] = 0;
_id = _unspecified;
_super = _unspecified;
_interfaces->clear();
_source = NULL;
_interfaces_specified = false;
{
int len = (int)strlen(_line);
int i;
// Replace \t\r\n with ' '
for (i=0; i<len; i++) {
if (_line[i] == '\t' || _line[i] == '\r' || _line[i] == '\n') {
_line[i] = ' ';
}
}
// Remove trailing newline/space
while (len > 0) {
if (_line[len-1] == ' ') {
_line[len-1] = '\0';
len --;
} else {
break;
}
}
_line_len = len;
_class_name = _line;
}
if ((_token = strchr(_line, ' ')) == NULL) {
// No optional arguments are specified.
return true;
}
// Mark the end of the name, and go to the next input char
*_token++ = '\0';
while (*_token) {
skip_whitespaces();
if (parse_int_option("id:", &_id)) {
continue;
} else if (parse_int_option("super:", &_super)) {
check_already_loaded("Super class", _super);
continue;
} else if (skip_token("interfaces:")) {
int i;
while (try_parse_int(&i)) {
check_already_loaded("Interface", i);
_interfaces->append(i);
}
} else if (skip_token("source:")) {
skip_whitespaces();
_source = _token;
char* s = strchr(_token, ' ');
if (s == NULL) {
break; // end of input line
} else {
*s = '\0'; // mark the end of _source
_token = s+1;
}
} else {
error("Unknown input");
}
}
// if src is specified
// id super interfaces must all be specified
// loader may be specified
// else
// # the class is loaded from classpath
// id may be specified
// super, interfaces, loader must not be specified
return true;
}
void ClassListParser::skip_whitespaces() {
while (*_token == ' ' || *_token == '\t') {
_token ++;
}
}
void ClassListParser::skip_non_whitespaces() {
while (*_token && *_token != ' ' && *_token != '\t') {
_token ++;
}
}
void ClassListParser::parse_int(int* value) {
skip_whitespaces();
if (sscanf(_token, "%i", value) == 1) {
skip_non_whitespaces();
if (*value < 0) {
error("Error: negative integers not allowed (%d)", *value);
}
} else {
error("Error: expected integer");
}
}
bool ClassListParser::try_parse_int(int* value) {
skip_whitespaces();
if (sscanf(_token, "%i", value) == 1) {
skip_non_whitespaces();
return true;
}
return false;
}
bool ClassListParser::skip_token(const char* option_name) {
size_t len = strlen(option_name);
if (strncmp(_token, option_name, len) == 0) {
_token += len;
return true;
} else {
return false;
}
}
bool ClassListParser::parse_int_option(const char* option_name, int* value) {
if (skip_token(option_name)) {
if (*value != _unspecified) {
error("%s specified twice", option_name);
} else {
parse_int(value);
return true;
}
}
return false;
}
void ClassListParser::print_specified_interfaces() {
const int n = _interfaces->length();
jio_fprintf(defaultStream::error_stream(), "Currently specified interfaces[%d] = {\n", n);
for (int i=0; i<n; i++) {
InstanceKlass* k = lookup_class_by_id(_interfaces->at(i));
jio_fprintf(defaultStream::error_stream(), " %4d = %s\n", _interfaces->at(i), k->name()->as_klass_external_name());
}
jio_fprintf(defaultStream::error_stream(), "}\n");
}
void ClassListParser::print_actual_interfaces(InstanceKlass *ik) {
int n = ik->local_interfaces()->length();
jio_fprintf(defaultStream::error_stream(), "Actual interfaces[%d] = {\n", n);
for (int i = 0; i < n; i++) {
InstanceKlass* e = InstanceKlass::cast(ik->local_interfaces()->at(i));
jio_fprintf(defaultStream::error_stream(), " %s\n", e->name()->as_klass_external_name());
}
jio_fprintf(defaultStream::error_stream(), "}\n");
}
void ClassListParser::error(const char *msg, ...) {
va_list ap;
va_start(ap, msg);
int error_index = _token - _line;
if (error_index >= _line_len) {
error_index = _line_len - 1;
}
if (error_index < 0) {
error_index = 0;
}
jio_fprintf(defaultStream::error_stream(),
"An error has occurred while processing class list file %s %d:%d.\n",
_classlist_file, _line_no, (error_index + 1));
jio_vfprintf(defaultStream::error_stream(), msg, ap);
if (_line_len <= 0) {
jio_fprintf(defaultStream::error_stream(), "\n");
} else {
jio_fprintf(defaultStream::error_stream(), ":\n");
for (int i=0; i<_line_len; i++) {
char c = _line[i];
if (c == '\0') {
jio_fprintf(defaultStream::error_stream(), "%s", " ");
} else {
jio_fprintf(defaultStream::error_stream(), "%c", c);
}
}
jio_fprintf(defaultStream::error_stream(), "\n");
for (int i=0; i<error_index; i++) {
jio_fprintf(defaultStream::error_stream(), "%s", " ");
}
jio_fprintf(defaultStream::error_stream(), "^\n");
}
vm_exit_during_initialization("class list format error.", NULL);
va_end(ap);
}
// This function is used for loading classes for customized class loaders
// during archive dumping.
InstanceKlass* ClassListParser::load_class_from_source(Symbol* class_name, TRAPS) {
#if !((defined(LINUX) && defined(X86) && defined(_LP64)) || \
(defined(SOLARIS) && defined(_LP64)))
// The only supported platforms are: (1) Linux/AMD64; (2) Solaris/64-bit
error("AppCDS custom class loaders not supported on this platform");
#endif
assert(UseAppCDS, "must be");
if (!is_super_specified()) {
error("If source location is specified, super class must be also specified");
}
if (!is_id_specified()) {
error("If source location is specified, id must be also specified");
}
InstanceKlass* k = ClassLoaderExt::load_class(class_name, _source, THREAD);
if (strncmp(_class_name, "java/", 5) == 0) {
log_info(cds)("Prohibited package for non-bootstrap classes: %s.class from %s",
_class_name, _source);
return NULL;
}
if (k != NULL) {
if (k->local_interfaces()->length() != _interfaces->length()) {
print_specified_interfaces();
print_actual_interfaces(k);
error("The number of interfaces (%d) specified in class list does not match the class file (%d)",
_interfaces->length(), k->local_interfaces()->length());
}
if (!SystemDictionaryShared::add_non_builtin_klass(class_name, ClassLoaderData::the_null_class_loader_data(),
k, THREAD)) {
error("Duplicated class %s", _class_name);
}
// This tells JVM_FindLoadedClass to not find this class.
k->set_shared_classpath_index(UNREGISTERED_INDEX);
}
return k;
}
InstanceKlass* ClassListParser::load_current_class(TRAPS) {
TempNewSymbol class_name_symbol = SymbolTable::new_symbol(_class_name, THREAD);
guarantee(!HAS_PENDING_EXCEPTION, "Exception creating a symbol.");
InstanceKlass *klass = NULL;
if (!is_loading_from_source()) {
if (is_super_specified()) {
error("If source location is not specified, super class must not be specified");
}
if (are_interfaces_specified()) {
error("If source location is not specified, interface(s) must not be specified");
}
bool non_array = !FieldType::is_array(class_name_symbol);
Handle s = java_lang_String::create_from_symbol(class_name_symbol, CHECK_0);
// Translate to external class name format, i.e., convert '/' chars to '.'
Handle string = java_lang_String::externalize_classname(s, CHECK_0);
JavaValue result(T_OBJECT);
InstanceKlass* spec_klass = non_array ?
SystemDictionary::ClassLoader_klass() : SystemDictionary::Class_klass();
Symbol* method_name = non_array ?
vmSymbols::loadClass_name() : vmSymbols::forName_name();
Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
if (non_array) {
JavaCalls::call_virtual(&result,
loader, //SystemDictionary::java_system_loader(),
spec_klass,
method_name, //vmSymbols::loadClass_name(),
vmSymbols::string_class_signature(),
string,
THREAD);
} else {
JavaCalls::call_static(&result,
spec_klass,
method_name,
vmSymbols::string_class_signature(),
string,
CHECK_NULL);
}
assert(result.get_type() == T_OBJECT, "just checking");
oop obj = (oop) result.get_jobject();
if (!HAS_PENDING_EXCEPTION && (obj != NULL)) {
if (non_array) {
klass = InstanceKlass::cast(java_lang_Class::as_Klass(obj));
} else {
klass = static_cast<InstanceKlass*>(java_lang_Class::array_klass_acquire(obj));
}
} else { // load classes in bootclasspath/a
if (HAS_PENDING_EXCEPTION) {
CLEAR_PENDING_EXCEPTION;
}
if (non_array) {
Klass* k = SystemDictionary::resolve_or_null(class_name_symbol, CHECK_NULL);
if (k != NULL) {
klass = InstanceKlass::cast(k);
} else {
if (!HAS_PENDING_EXCEPTION) {
THROW_NULL(vmSymbols::java_lang_ClassNotFoundException());
}
}
}
}
} else {
// If "source:" tag is specified, all super class and super interfaces must be specified in the
// class list file.
if (UseAppCDS) {
klass = load_class_from_source(class_name_symbol, CHECK_NULL);
}
}
if (klass != NULL && is_id_specified()) {
int id = this->id();
SystemDictionaryShared::update_shared_entry(klass, id);
InstanceKlass* old = table()->lookup(id);
if (old != NULL && old != klass) {
error("Duplicated ID %d for class %s", id, _class_name);
}
table()->add(id, klass);
}
return klass;
}
bool ClassListParser::is_loading_from_source() {
return (_source != NULL);
}
InstanceKlass* ClassListParser::lookup_class_by_id(int id) {
InstanceKlass* klass = table()->lookup(id);
if (klass == NULL) {
error("Class ID %d has not been defined", id);
}
return klass;
}
InstanceKlass* ClassListParser::lookup_super_for_current_class(Symbol* super_name) {
if (!is_loading_from_source()) {
return NULL;
}
InstanceKlass* k = lookup_class_by_id(super());
if (super_name != k->name()) {
error("The specified super class %s (id %d) does not match actual super class %s",
k->name()->as_klass_external_name(), super(),
super_name->as_klass_external_name());
}
return k;
}
InstanceKlass* ClassListParser::lookup_interface_for_current_class(Symbol* interface_name) {
if (!is_loading_from_source()) {
return NULL;
}
const int n = _interfaces->length();
if (n == 0) {
error("Class %s implements the interface %s, but no interface has been specified in the input line",
_class_name, interface_name->as_klass_external_name());
ShouldNotReachHere();
}
int i;
for (i=0; i<n; i++) {
InstanceKlass* k = lookup_class_by_id(_interfaces->at(i));
if (interface_name == k->name()) {
return k;
}
}
// interface_name is not specified by the "interfaces:" keyword.
print_specified_interfaces();
error("The interface %s implemented by class %s does not match any of the specified interface IDs",
interface_name->as_klass_external_name(), _class_name);
ShouldNotReachHere();
return NULL;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2017, 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
@ -27,30 +27,122 @@
#include "utilities/exceptions.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/hashtable.hpp"
class CDSClassInfo;
// Look up from ID -> InstanceKlass*
class ID2KlassTable : public Hashtable<InstanceKlass*, mtClass> {
public:
ID2KlassTable() : Hashtable<InstanceKlass*, mtClass>(1987, sizeof(HashtableEntry<InstanceKlass*, mtClass>)) { }
void add(int id, InstanceKlass* klass) {
unsigned int hash = (unsigned int)id;
HashtableEntry<InstanceKlass*, mtClass>* entry = new_entry(hash, klass);
add_entry(hash_to_index(hash), entry);
}
InstanceKlass* lookup(int id) {
unsigned int hash = (unsigned int)id;
int index = hash_to_index(id);
for (HashtableEntry<InstanceKlass*, mtClass>* e = bucket(index); e != NULL; e = e->next()) {
if (e->hash() == hash) {
return e->literal();
}
}
return NULL;
}
};
class ClassListParser : public StackObj {
enum {
_unspecified = -999,
// Max number of bytes allowed per line in the classlist.
// Theoretically Java class names could be 65535 bytes in length. In reality,
// Theoretically Java class names could be 65535 bytes in length. Also, an input line
// could have a very long path name up to JVM_MAXPATHLEN bytes in length. In reality,
// 4K bytes is more than enough.
_max_allowed_line_len = 4096,
_line_buf_extra = 10, // for detecting input too long
_line_buf_size = _max_allowed_line_len + _line_buf_extra
};
static ClassListParser* _instance; // the singleton.
const char* _classlist_file;
FILE* _file;
char _line[_line_buf_size]; // The buffer that holds the current line.
ID2KlassTable _id2klass_table;
// The following field contains information from the *current* line being
// parsed.
char _line[_line_buf_size]; // The buffer that holds the current line. Some characters in
// the buffer may be overwritten by '\0' during parsing.
int _line_len; // Original length of the input line.
int _line_no; // Line number for current line being parsed
const char* _class_name;
int _id;
int _super;
GrowableArray<int>* _interfaces;
bool _interfaces_specified;
const char* _source;
bool parse_int_option(const char* option_name, int* value);
InstanceKlass* load_class_from_source(Symbol* class_name, TRAPS);
ID2KlassTable *table() {
return &_id2klass_table;
}
InstanceKlass* lookup_class_by_id(int id);
void print_specified_interfaces();
void print_actual_interfaces(InstanceKlass *ik);
public:
ClassListParser(const char* file);
~ClassListParser();
static ClassListParser* instance() {
return _instance;
}
bool parse_one_line();
char* _token;
void error(const char* msg, ...);
void parse_int(int* value);
bool try_parse_int(int* value);
bool skip_token(const char* option_name);
void skip_whitespaces();
void skip_non_whitespaces();
bool is_id_specified() {
return _id != _unspecified;
}
bool is_super_specified() {
return _super != _unspecified;
}
bool are_interfaces_specified() {
return _interfaces->length() > 0;
}
int id() {
assert(is_id_specified(), "do not query unspecified id");
return _id;
}
int super() {
assert(is_super_specified(), "do not query unspecified super");
return _super;
}
void check_already_loaded(const char* which, int id) {
if (_id2klass_table.lookup(id) == NULL) {
error("%s id %d is not yet loaded", which, id);
}
}
const char* current_class_name() {
return _line;
return _class_name;
}
InstanceKlass* load_current_class(TRAPS);
bool is_loading_from_source();
// Look up the super or interface of the current class being loaded
// (in this->load_current_class()).
InstanceKlass* lookup_super_for_current_class(Symbol* super_name);
InstanceKlass* lookup_interface_for_current_class(Symbol* interface_name);
};
#endif // SHARE_VM_MEMORY_CLASSLISTPARSER_HPP
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2017, 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
@ -23,14 +23,329 @@
*/
#include "precompiled.hpp"
#include "classfile/classFileParser.hpp"
#include "classfile/classFileStream.hpp"
#include "classfile/classListParser.hpp"
#include "classfile/classLoader.hpp"
#include "classfile/classLoaderExt.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/klassFactory.hpp"
#include "classfile/sharedClassUtil.hpp"
#include "classfile/sharedPathsMiscInfo.hpp"
#include "classfile/systemDictionaryShared.hpp"
#include "classfile/vmSymbols.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/filemap.hpp"
#include "memory/resourceArea.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/oop.inline.hpp"
#include "oops/symbol.hpp"
#include "runtime/arguments.hpp"
#include "runtime/java.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/os.hpp"
#include "services/threadService.hpp"
#include "utilities/stringUtils.hpp"
jshort ClassLoaderExt::_app_paths_start_index = ClassLoaderExt::max_classpath_index;
bool ClassLoaderExt::_has_app_classes = false;
bool ClassLoaderExt::_has_platform_classes = false;
void ClassLoaderExt::setup_app_search_path() {
assert(DumpSharedSpaces, "this function is only used with -Xshare:dump and -XX:+UseAppCDS");
_app_paths_start_index = ClassLoader::num_boot_classpath_entries();
char* app_class_path = os::strdup(Arguments::get_appclasspath());
if (strcmp(app_class_path, ".") == 0) {
// This doesn't make any sense, even for AppCDS, so let's skip it. We
// don't want to throw an error here because -cp "." is usually assigned
// by the launcher when classpath is not specified.
trace_class_path("app loader class path (skipped)=", app_class_path);
} else {
trace_class_path("app loader class path=", app_class_path);
shared_paths_misc_info()->add_app_classpath(app_class_path);
ClassLoader::setup_app_search_path(app_class_path);
}
}
char* ClassLoaderExt::read_manifest(ClassPathEntry* entry, jint *manifest_size, bool clean_text, TRAPS) {
const char* name = "META-INF/MANIFEST.MF";
char* manifest;
jint size;
assert(entry->is_jar_file(), "must be");
manifest = (char*) ((ClassPathZipEntry*)entry )->open_entry(name, &size, true, CHECK_NULL);
if (manifest == NULL) { // No Manifest
*manifest_size = 0;
return NULL;
}
if (clean_text) {
// See http://docs.oracle.com/javase/6/docs/technotes/guides/jar/jar.html#JAR%20Manifest
// (1): replace all CR/LF and CR with LF
StringUtils::replace_no_expand(manifest, "\r\n", "\n");
// (2) remove all new-line continuation (remove all "\n " substrings)
StringUtils::replace_no_expand(manifest, "\n ", "");
}
*manifest_size = (jint)strlen(manifest);
return manifest;
}
char* ClassLoaderExt::get_class_path_attr(const char* jar_path, char* manifest, jint manifest_size) {
const char* tag = "Class-Path: ";
const int tag_len = (int)strlen(tag);
char* found = NULL;
char* line_start = manifest;
char* end = manifest + manifest_size;
assert(*end == 0, "must be nul-terminated");
while (line_start < end) {
char* line_end = strchr(line_start, '\n');
if (line_end == NULL) {
// JAR spec require the manifest file to be terminated by a new line.
break;
}
if (strncmp(tag, line_start, tag_len) == 0) {
if (found != NULL) {
// Same behavior as jdk/src/share/classes/java/util/jar/Attributes.java
// If duplicated entries are found, the last one is used.
tty->print_cr("Warning: Duplicate name in Manifest: %s.\n"
"Ensure that the manifest does not have duplicate entries, and\n"
"that blank lines separate individual sections in both your\n"
"manifest and in the META-INF/MANIFEST.MF entry in the jar file:\n%s\n", tag, jar_path);
}
found = line_start + tag_len;
assert(found <= line_end, "sanity");
*line_end = '\0';
}
line_start = line_end + 1;
}
return found;
}
void ClassLoaderExt::process_jar_manifest(ClassPathEntry* entry,
bool check_for_duplicates) {
Thread* THREAD = Thread::current();
ResourceMark rm(THREAD);
jint manifest_size;
char* manifest = read_manifest(entry, &manifest_size, CHECK);
if (manifest == NULL) {
return;
}
if (strstr(manifest, "Extension-List:") != NULL) {
tty->print_cr("-Xshare:dump does not support Extension-List in JAR manifest: %s", entry->name());
vm_exit(1);
}
char* cp_attr = get_class_path_attr(entry->name(), manifest, manifest_size);
if (cp_attr != NULL && strlen(cp_attr) > 0) {
trace_class_path("found Class-Path: ", cp_attr);
char sep = os::file_separator()[0];
const char* dir_name = entry->name();
const char* dir_tail = strrchr(dir_name, sep);
int dir_len;
if (dir_tail == NULL) {
dir_len = 0;
} else {
dir_len = dir_tail - dir_name + 1;
}
// Split the cp_attr by spaces, and add each file
char* file_start = cp_attr;
char* end = file_start + strlen(file_start);
while (file_start < end) {
char* file_end = strchr(file_start, ' ');
if (file_end != NULL) {
*file_end = 0;
file_end += 1;
} else {
file_end = end;
}
int name_len = (int)strlen(file_start);
if (name_len > 0) {
ResourceMark rm(THREAD);
char* libname = NEW_RESOURCE_ARRAY(char, dir_len + name_len + 1);
*libname = 0;
strncat(libname, dir_name, dir_len);
strncat(libname, file_start, name_len);
trace_class_path("library = ", libname);
ClassLoader::update_class_path_entry_list(libname, true, false);
}
file_start = file_end;
}
}
}
void ClassLoaderExt::setup_search_paths() {
if (UseAppCDS) {
shared_paths_misc_info()->record_app_offset();
ClassLoaderExt::setup_app_search_path();
}
}
Thread* ClassLoaderExt::Context::_dump_thread = NULL;
bool ClassLoaderExt::check(ClassLoaderExt::Context *context,
const ClassFileStream* stream,
const int classpath_index) {
if (stream != NULL) {
// Ignore any App classes from signed JAR file during CDS archiving
// dumping
if (DumpSharedSpaces &&
SharedClassUtil::is_classpath_entry_signed(classpath_index) &&
classpath_index >= _app_paths_start_index) {
tty->print_cr("Preload Warning: Skipping %s from signed JAR",
context->class_name());
return false;
}
if (classpath_index >= _app_paths_start_index) {
_has_app_classes = true;
_has_platform_classes = true;
}
}
return true;
}
void ClassLoaderExt::record_result(ClassLoaderExt::Context *context,
Symbol* class_name,
const s2 classpath_index,
InstanceKlass* result,
TRAPS) {
assert(DumpSharedSpaces, "Sanity");
// We need to remember where the class comes from during dumping.
oop loader = result->class_loader();
s2 classloader_type = ClassLoader::BOOT_LOADER;
if (SystemDictionary::is_system_class_loader(loader)) {
classloader_type = ClassLoader::APP_LOADER;
ClassLoaderExt::set_has_app_classes();
} else if (SystemDictionary::is_platform_class_loader(loader)) {
classloader_type = ClassLoader::PLATFORM_LOADER;
ClassLoaderExt::set_has_platform_classes();
}
result->set_shared_classpath_index(classpath_index);
result->set_class_loader_type(classloader_type);
}
void ClassLoaderExt::finalize_shared_paths_misc_info() {
if (UseAppCDS) {
if (!_has_app_classes) {
shared_paths_misc_info()->pop_app();
}
}
}
// Load the class of the given name from the location given by path. The path is specified by
// the "source:" in the class list file (see classListParser.cpp), and can be a directory or
// a JAR file.
InstanceKlass* ClassLoaderExt::load_class(Symbol* name, const char* path, TRAPS) {
assert(name != NULL, "invariant");
assert(DumpSharedSpaces && UseAppCDS, "this function is only used with -Xshare:dump and -XX:+UseAppCDS");
ResourceMark rm(THREAD);
const char* class_name = name->as_C_string();
const char* file_name = file_name_for_class_name(class_name,
name->utf8_length());
assert(file_name != NULL, "invariant");
// Lookup stream for parsing .class file
ClassFileStream* stream = NULL;
ClassPathEntry* e = find_classpath_entry_from_cache(path, CHECK_NULL);
if (e == NULL) {
return NULL;
}
{
PerfClassTraceTime vmtimer(perf_sys_class_lookup_time(),
((JavaThread*) THREAD)->get_thread_stat()->perf_timers_addr(),
PerfClassTraceTime::CLASS_LOAD);
stream = e->open_stream(file_name, CHECK_NULL);
}
if (NULL == stream) {
tty->print_cr("Preload Warning: Cannot find %s", class_name);
return NULL;
}
assert(stream != NULL, "invariant");
stream->set_verify(true);
ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();
Handle protection_domain;
InstanceKlass* result = KlassFactory::create_from_stream(stream,
name,
loader_data,
protection_domain,
NULL, // host_klass
NULL, // cp_patches
THREAD);
if (HAS_PENDING_EXCEPTION) {
tty->print_cr("Preload Error: Failed to load %s", class_name);
return NULL;
}
result->set_shared_classpath_index(UNREGISTERED_INDEX);
SystemDictionaryShared::set_shared_class_misc_info(result, stream);
return result;
}
struct CachedClassPathEntry {
const char* _path;
ClassPathEntry* _entry;
};
static GrowableArray<CachedClassPathEntry>* cached_path_entries = NULL;
ClassPathEntry* ClassLoaderExt::find_classpath_entry_from_cache(const char* path, TRAPS) {
// This is called from dump time so it's single threaded and there's no need for a lock.
assert(DumpSharedSpaces && UseAppCDS, "this function is only used with -Xshare:dump and -XX:+UseAppCDS");
if (cached_path_entries == NULL) {
cached_path_entries = new (ResourceObj::C_HEAP, mtClass) GrowableArray<CachedClassPathEntry>(20, /*c heap*/ true);
}
CachedClassPathEntry ccpe;
for (int i=0; i<cached_path_entries->length(); i++) {
ccpe = cached_path_entries->at(i);
if (strcmp(ccpe._path, path) == 0) {
if (i != 0) {
// Put recent entries at the beginning to speed up searches.
cached_path_entries->remove_at(i);
cached_path_entries->insert_before(0, ccpe);
}
return ccpe._entry;
}
}
struct stat st;
if (os::stat(path, &st) != 0) {
// File or directory not found
return NULL;
}
ClassPathEntry* new_entry = NULL;
new_entry = create_class_path_entry(path, &st, false, false, CHECK_NULL);
if (new_entry == NULL) {
return NULL;
}
ccpe._path = strdup(path);
ccpe._entry = new_entry;
cached_path_entries->insert_before(0, ccpe);
return new_entry;
}
Klass* ClassLoaderExt::load_one_class(ClassListParser* parser, TRAPS) {
TempNewSymbol class_name_symbol = SymbolTable::new_symbol(parser->current_class_name(), THREAD);
guarantee(!HAS_PENDING_EXCEPTION, "Exception creating a symbol.");
return SystemDictionary::resolve_or_null(class_name_symbol, THREAD);
return parser->load_current_class(THREAD);
}

View File

@ -26,65 +26,152 @@
#define SHARE_VM_CLASSFILE_CLASSLOADEREXT_HPP
#include "classfile/classLoader.hpp"
#include "classfile/systemDictionary.hpp"
#include "oops/instanceKlass.hpp"
#include "runtime/handles.hpp"
#include "utilities/macros.hpp"
class ClassListParser;
CDS_ONLY(class SharedPathsMiscInfoExt;)
CDS_ONLY(class ClassListParser;)
class ClassLoaderExt: public ClassLoader { // AllStatic
public:
enum SomeConstants {
max_classpath_index = 0x7fff
};
// ClassLoaderExt::Context --
//
// This is used by DumpSharedSpaces only - it enforces the same classloader
// delegation model as would be in run-time. I.e.,
// + classes defined by the NULL class loader cannot load classes in the PLATFORM or APP paths.
// + classes defined by the PLATFORM class loader cannot load classes in the APP paths.
class Context {
static Thread* _dump_thread;
const char* _class_name;
const char* _file_name;
public:
const char* class_name() {
return _class_name;
}
const char* file_name() {
return _file_name;
}
Context(const char* class_name, const char* file_name, TRAPS) {
_class_name = class_name;
_file_name = file_name;
#if INCLUDE_CDS
if (!DumpSharedSpaces && !UseSharedSpaces) {
// Must not modify _app_paths_start_index if we're not using CDS.
assert(_app_paths_start_index == ClassLoaderExt::max_classpath_index, "must be");
}
#endif
}
bool check(const ClassFileStream* stream, const int classpath_index) {
return true;
CDS_ONLY(return ClassLoaderExt::check(this, stream, classpath_index);)
NOT_CDS(return true;)
}
bool should_verify(int classpath_index) {
return false;
CDS_ONLY(return (classpath_index >= _app_paths_start_index);)
NOT_CDS(return false;)
}
void record_result(Symbol* class_name,
const s2 classpath_index,
InstanceKlass* result, TRAPS) {
InstanceKlass* result,
TRAPS) {
#if INCLUDE_CDS
assert(DumpSharedSpaces, "Sanity");
oop loader = result->class_loader();
s2 classloader_type = ClassLoader::BOOT_LOADER;
if (SystemDictionary::is_system_class_loader(loader)) {
classloader_type = ClassLoader::APP_LOADER;
ClassLoaderExt::set_has_app_classes();
} else if (SystemDictionary::is_platform_class_loader(loader)) {
classloader_type = ClassLoader::PLATFORM_LOADER;
ClassLoaderExt::set_has_platform_classes();
}
result->set_shared_classpath_index(classpath_index);
result->set_class_loader_type(classloader_type);
ClassLoaderExt::record_result(this, class_name, classpath_index, result, THREAD);
#endif
}
};
~Context() {
#if INCLUDE_CDS
if (!DumpSharedSpaces && !UseSharedSpaces) {
// Must not modify app_paths_start_index if we're not using CDS.
assert(_app_paths_start_index == ClassLoaderExt::max_classpath_index, "must be");
}
#endif
}
}; // end ClassLoaderExt::Context
private:
#if INCLUDE_CDS
static char* get_class_path_attr(const char* jar_path, char* manifest, jint manifest_size);
static void setup_app_search_path(); // Only when -Xshare:dump
static SharedPathsMiscInfoExt* shared_paths_misc_info() {
return (SharedPathsMiscInfoExt*)_shared_paths_misc_info;
}
static jshort _app_paths_start_index; // index of first app JAR in shared classpath entry table
static bool _has_app_classes;
static bool _has_platform_classes;
#endif
public:
CDS_ONLY(static void process_jar_manifest(ClassPathEntry* entry, bool check_for_duplicates);)
// Called by JVMTI code to add boot classpath
static void append_boot_classpath(ClassPathEntry* new_entry) {
#if INCLUDE_CDS
if (UseAppCDS) {
warning("UseAppCDS is disabled because bootstrap classpath has been appended");
UseAppCDS = false;
}
#endif
ClassLoader::add_to_boot_append_entries(new_entry);
}
static void setup_search_paths() {}
static bool is_boot_classpath(int classpath_index) {
return true;
}
static Klass* load_one_class(ClassListParser* parser, TRAPS);
static void setup_search_paths() NOT_CDS_RETURN;
#if INCLUDE_CDS
static void set_has_app_classes() {}
static void set_has_platform_classes() {}
private:
static char* read_manifest(ClassPathEntry* entry, jint *manifest_size, bool clean_text, TRAPS);
static ClassPathEntry* find_classpath_entry_from_cache(const char* path, TRAPS);
public:
static char* read_manifest(ClassPathEntry* entry, jint *manifest_size, TRAPS) {
return NULL;
// Remove all the new-line continuations (which wrap long lines at 72 characters, see
// http://docs.oracle.com/javase/6/docs/technotes/guides/jar/jar.html#JAR%20Manifest), so
// that the manifest is easier to parse.
return read_manifest(entry, manifest_size, true, THREAD);
}
static char* read_raw_manifest(ClassPathEntry* entry, jint *manifest_size, TRAPS) {
// Do not remove new-line continuations, so we can easily pass it as an argument to
// java.util.jar.Manifest.getManifest() at run-time.
return read_manifest(entry, manifest_size, false, THREAD);
}
static void finalize_shared_paths_misc_info();
static jshort app_paths_start_index() { return _app_paths_start_index; }
static void init_paths_start_index(jshort app_start) {
_app_paths_start_index = app_start;
}
static bool is_boot_classpath(int classpath_index) {
return classpath_index < _app_paths_start_index;
}
static bool has_platform_or_app_classes() {
return _has_app_classes || _has_platform_classes;
}
static bool check(class ClassLoaderExt::Context *context,
const ClassFileStream* stream,
const int classpath_index);
static void record_result(class ClassLoaderExt::Context *context,
Symbol* class_name,
const s2 classpath_index,
InstanceKlass* result, TRAPS);
static InstanceKlass* load_class(Symbol* h_name, const char* path, TRAPS);
static Klass* load_one_class(ClassListParser* parser, TRAPS);
static void set_has_app_classes() {
_has_app_classes = true;
}
static void set_has_platform_classes() {
_has_platform_classes = true;
}
static void process_jar_manifest(ClassPathEntry* entry, bool check_for_duplicates) {}
#endif
};

View File

@ -0,0 +1,248 @@
/*
* Copyright (c) 2014, 2017, 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 "classfile/classLoader.hpp"
#include "classfile/classLoaderExt.hpp"
#include "classfile/dictionary.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/sharedClassUtil.hpp"
#include "classfile/stringTable.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/systemDictionaryShared.hpp"
#include "memory/filemap.hpp"
#include "memory/metadataFactory.hpp"
#include "memory/resourceArea.hpp"
#include "oops/instanceKlass.hpp"
#include "runtime/arguments.hpp"
#include "runtime/java.hpp"
#include "runtime/os.hpp"
class ManifestStream: public ResourceObj {
private:
u1* _buffer_start; // Buffer bottom
u1* _buffer_end; // Buffer top (one past last element)
u1* _current; // Current buffer position
public:
// Constructor
ManifestStream(u1* buffer, int length) : _buffer_start(buffer),
_current(buffer) {
_buffer_end = buffer + length;
}
static bool is_attr(u1* attr, const char* name) {
return strncmp((const char*)attr, name, strlen(name)) == 0;
}
static char* copy_attr(u1* value, size_t len) {
char* buf = NEW_RESOURCE_ARRAY(char, len + 1);
strncpy(buf, (char*)value, len);
buf[len] = 0;
return buf;
}
// The return value indicates if the JAR is signed or not
bool check_is_signed() {
u1* attr = _current;
bool isSigned = false;
while (_current < _buffer_end) {
if (*_current == '\n') {
*_current = '\0';
u1* value = (u1*)strchr((char*)attr, ':');
if (value != NULL) {
assert(*(value+1) == ' ', "Unrecognized format" );
if (strstr((char*)attr, "-Digest") != NULL) {
isSigned = true;
break;
}
}
*_current = '\n'; // restore
attr = _current + 1;
}
_current ++;
}
return isSigned;
}
};
void SharedPathsMiscInfoExt::print_path(outputStream* out, int type, const char* path) {
switch(type) {
case APP:
ClassLoader::trace_class_path("Expecting -Djava.class.path=", path);
break;
default:
SharedPathsMiscInfo::print_path(out, type, path);
}
}
bool SharedPathsMiscInfoExt::check(jint type, const char* path) {
switch (type) {
case APP:
{
// Prefix is OK: E.g., dump with -cp foo.jar, but run with -cp foo.jar:bar.jar
size_t len = strlen(path);
const char *appcp = Arguments::get_appclasspath();
assert(appcp != NULL, "NULL app classpath");
size_t appcp_len = strlen(appcp);
if (appcp_len < len) {
return fail("Run time APP classpath is shorter than the one at dump time: ", appcp);
}
ResourceMark rm;
char* tmp_path;
if (len == appcp_len) {
tmp_path = (char*)appcp;
} else {
tmp_path = NEW_RESOURCE_ARRAY(char, len + 1);
strncpy(tmp_path, appcp, len);
tmp_path[len] = 0;
}
if (os::file_name_strcmp(path, tmp_path) != 0) {
return fail("[APP classpath mismatch, actual: -Djava.class.path=", appcp);
}
if (appcp[len] != '\0' && appcp[len] != os::path_separator()[0]) {
return fail("Dump time APP classpath is not a proper prefix of run time APP classpath: ", appcp);
}
}
break;
default:
return SharedPathsMiscInfo::check(type, path);
}
return true;
}
void SharedClassUtil::update_shared_classpath(ClassPathEntry *cpe, SharedClassPathEntry* e, TRAPS) {
ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();
SharedClassPathEntryExt* ent = (SharedClassPathEntryExt*)e;
ResourceMark rm(THREAD);
jint manifest_size;
bool isSigned;
char* manifest = ClassLoaderExt::read_manifest(cpe, &manifest_size, CHECK);
if (manifest != NULL) {
ManifestStream* stream = new ManifestStream((u1*)manifest,
manifest_size);
isSigned = stream->check_is_signed();
if (isSigned) {
ent->_is_signed = true;
} else {
// Copy the manifest into the shared archive
manifest = ClassLoaderExt::read_raw_manifest(cpe, &manifest_size, CHECK);
Array<u1>* buf = MetadataFactory::new_array<u1>(loader_data,
manifest_size,
THREAD);
char* p = (char*)(buf->data());
memcpy(p, manifest, manifest_size);
ent->set_manifest(buf);
ent->_is_signed = false;
}
}
}
void SharedClassUtil::initialize(TRAPS) {
if (UseSharedSpaces) {
int size = FileMapInfo::get_number_of_share_classpaths();
if (size > 0) {
SystemDictionaryShared::allocate_shared_data_arrays(size, THREAD);
if (!DumpSharedSpaces) {
FileMapHeaderExt* header = (FileMapHeaderExt*)FileMapInfo::current_info()->header();
ClassLoaderExt::init_paths_start_index(header->_app_paths_start_index);
}
}
}
if (DumpSharedSpaces) {
if (SharedArchiveConfigFile) {
read_extra_data(SharedArchiveConfigFile, THREAD);
}
}
}
void SharedClassUtil::read_extra_data(const char* filename, TRAPS) {
HashtableTextDump reader(filename);
reader.check_version("VERSION: 1.0");
while (reader.remain() > 0) {
int utf8_length;
int prefix_type = reader.scan_prefix(&utf8_length);
ResourceMark rm(THREAD);
char* utf8_buffer = NEW_RESOURCE_ARRAY(char, utf8_length);
reader.get_utf8(utf8_buffer, utf8_length);
if (prefix_type == HashtableTextDump::SymbolPrefix) {
SymbolTable::new_symbol(utf8_buffer, utf8_length, THREAD);
} else{
assert(prefix_type == HashtableTextDump::StringPrefix, "Sanity");
utf8_buffer[utf8_length] = '\0';
oop s = StringTable::intern(utf8_buffer, THREAD);
}
}
}
bool SharedClassUtil::is_classpath_entry_signed(int classpath_index) {
assert(classpath_index >= 0, "Sanity");
SharedClassPathEntryExt* ent = (SharedClassPathEntryExt*)
FileMapInfo::shared_classpath(classpath_index);
return ent->_is_signed;
}
void FileMapHeaderExt::populate(FileMapInfo* mapinfo, size_t alignment) {
FileMapInfo::FileMapHeader::populate(mapinfo, alignment);
ClassLoaderExt::finalize_shared_paths_misc_info();
_app_paths_start_index = ClassLoaderExt::app_paths_start_index();
_verify_local = BytecodeVerificationLocal;
_verify_remote = BytecodeVerificationRemote;
_has_platform_or_app_classes = ClassLoaderExt::has_platform_or_app_classes();
}
bool FileMapHeaderExt::validate() {
if (UseAppCDS) {
const char* prop = Arguments::get_property("java.system.class.loader");
if (prop != NULL) {
warning("UseAppCDS is disabled because the java.system.class.loader property is specified (value = \"%s\"). "
"To enable UseAppCDS, this property must be not be set", prop);
UseAppCDS = false;
}
}
if (!FileMapInfo::FileMapHeader::validate()) {
return false;
}
// For backwards compatibility, we don't check the verification setting
// if the archive only contains system classes.
if (_has_platform_or_app_classes &&
((!_verify_local && BytecodeVerificationLocal) ||
(!_verify_remote && BytecodeVerificationRemote))) {
FileMapInfo::fail_continue("The shared archive file was created with less restrictive "
"verification setting than the current setting.");
return false;
}
return true;
}

View File

@ -27,37 +27,108 @@
#include "classfile/sharedPathsMiscInfo.hpp"
#include "memory/filemap.hpp"
#include "classfile/classLoaderExt.hpp"
#include "classfile/dictionary.hpp"
#include "classfile/systemDictionaryShared.hpp"
#include "oops/klass.hpp"
class SharedClassUtil : AllStatic {
class FileMapHeaderExt: public FileMapInfo::FileMapHeader {
public:
jshort _app_paths_start_index; // Index of first app classpath entry
bool _verify_local; // BytecodeVerificationLocal setting
bool _verify_remote; // BytecodeVerificationRemote setting
bool _has_platform_or_app_classes; // Archive contains app classes
static SharedPathsMiscInfo* allocate_shared_paths_misc_info() {
return new SharedPathsMiscInfo();
FileMapHeaderExt() {
_has_platform_or_app_classes = true;
}
virtual void populate(FileMapInfo* mapinfo, size_t alignment);
virtual bool validate();
};
// In addition to SharedPathsMiscInfo, the following information is also stored
//
//
// + The value of Arguments::get_appclasspath() used during dumping.
//
class SharedPathsMiscInfoExt : public SharedPathsMiscInfo {
private:
int _app_offset;
public:
enum {
APP = 5
};
virtual const char* type_name(int type) {
switch (type) {
case APP: return "APP";
default: return SharedPathsMiscInfo::type_name(type);
}
}
static SharedPathsMiscInfo* allocate_shared_paths_misc_info(char* buf, int size) {
return new SharedPathsMiscInfo(buf, size);
virtual void print_path(outputStream* out, int type, const char* path);
SharedPathsMiscInfoExt() : SharedPathsMiscInfo() {
_app_offset = 0;
}
SharedPathsMiscInfoExt(char* buf, int size) : SharedPathsMiscInfo(buf, size) {
_app_offset = 0;
}
static FileMapInfo::FileMapHeader* allocate_file_map_header() {
return new FileMapInfo::FileMapHeader();
virtual bool check(jint type, const char* path);
void add_app_classpath(const char* path) {
add_path(path, APP);
}
static size_t file_map_header_size() {
return sizeof(FileMapInfo::FileMapHeader);
void record_app_offset() {
_app_offset = get_used_bytes();
}
static size_t shared_class_path_entry_size() {
return sizeof(SharedClassPathEntry);
}
static void update_shared_classpath(ClassPathEntry *cpe,
SharedClassPathEntry* ent, TRAPS) {}
static void initialize(TRAPS) {}
inline static bool is_shared_boot_class(Klass* klass) {
return (klass->_shared_class_path_index >= 0);
void pop_app() {
_cur_ptr = _buf_start + _app_offset;
write_jint(0);
}
};
class SharedClassPathEntryExt: public SharedClassPathEntry {
public:
//Maniest attributes
bool _is_signed;
void set_manifest(Array<u1>* manifest) {
_manifest = manifest;
}
};
class SharedClassUtil : AllStatic {
public:
static SharedPathsMiscInfo* allocate_shared_paths_misc_info() {
return new SharedPathsMiscInfoExt();
}
static SharedPathsMiscInfo* allocate_shared_paths_misc_info(char* buf, int size) {
return new SharedPathsMiscInfoExt(buf, size);
}
static FileMapInfo::FileMapHeader* allocate_file_map_header() {
return new FileMapHeaderExt();
}
static size_t file_map_header_size() {
return sizeof(FileMapHeaderExt);
}
static size_t shared_class_path_entry_size() {
return sizeof(SharedClassPathEntryExt);
}
static void update_shared_classpath(ClassPathEntry *cpe, SharedClassPathEntry* ent, TRAPS);
static void initialize(TRAPS);
private:
static void read_extra_data(const char* filename, TRAPS);
public:
static bool is_classpath_entry_signed(int classpath_index);
};
#endif // SHARE_VM_CLASSFILE_SHAREDCLASSUTIL_HPP

View File

@ -1087,7 +1087,7 @@ InstanceKlass* SystemDictionary::resolve_from_stream(Symbol* class_name,
#if INCLUDE_CDS
ResourceMark rm(THREAD);
if (DumpSharedSpaces && !class_loader.is_null() &&
!ArgumentsExt::using_AppCDS() && strcmp(class_name->as_C_string(), "Unnamed") != 0) {
!UseAppCDS && strcmp(class_name->as_C_string(), "Unnamed") != 0) {
// If AppCDS is not enabled, don't define the class at dump time (except for the "Unnamed"
// class, which is used by MethodHandles).
THROW_MSG_NULL(vmSymbols::java_lang_ClassNotFoundException(), class_name->as_C_string());

File diff suppressed because it is too large Load Diff

View File

@ -25,75 +25,362 @@
#ifndef SHARE_VM_CLASSFILE_SYSTEMDICTIONARYSHARED_HPP
#define SHARE_VM_CLASSFILE_SYSTEMDICTIONARYSHARED_HPP
#include "classfile/systemDictionary.hpp"
#include "oops/klass.hpp"
#include "classfile/dictionary.hpp"
#include "classfile/systemDictionary.hpp"
#include "memory/filemap.hpp"
/*===============================================================================
Handling of the classes in the AppCDS archive
To ensure safety and to simplify the implementation, archived classes are
"segregated" into several types. The following rules describe how they
are stored and looked up.
[1] Category of archived classes
There are 3 disjoint groups of classes stored in the AppCDS archive. They are
categorized as by their SharedDictionaryEntry::loader_type()
BUILTIN: These classes may be defined ONLY by the BOOT/PLATFORM/APP
loaders.
UNREGISTERED: These classes may be defined ONLY by a ClassLoader
instance that's not listed above (using fingerprint matching)
[2] How classes from different categories are specified in the classlist:
Starting from JDK9, each class in the classlist may be specified with
these keywords: "id", "super", "interfaces", "loader" and "source".
BUILTIN Only the "id" keyword may be (optionally) specified. All other
keywords are forbidden.
The named class is looked up from the jimage and from
Xbootclasspath/a and CLASSPATH.
UNREGISTERED: The "id", "super", and "source" keywords must all be
specified.
The "interfaces" keyword must be specified if the class implements
one or more local interfaces. The "interfaces" keyword must not be
specified if the class does not implement local interfaces.
The named class is looked up from the location specified in the
"source" keyword.
Example classlist:
# BUILTIN
java/lang/Object id: 0
java/lang/Cloneable id: 1
java/lang/String
# UNREGISTERED
Bar id: 3 super: 0 interfaces: 1 source: /foo.jar
[3] Identifying the loader_type of archived classes in the shared dictionary
Each archived Klass* C is associated with a SharedDictionaryEntry* E
BUILTIN: (C->shared_classpath_index() >= 0)
UNREGISTERED: (C->shared_classpath_index() < 0)
[4] Lookup of archived classes at run time:
(a) BUILTIN loaders:
Search the shared directory for a BUILTIN class with a matching name.
(b) UNREGISTERED loaders:
The search originates with SystemDictionaryShared::lookup_from_stream().
Search the shared directory for a UNREGISTERED class with a matching
(name, clsfile_len, clsfile_crc32) tuple.
===============================================================================*/
#define UNREGISTERED_INDEX -9999
class ClassFileStream;
class SystemDictionaryShared: public SystemDictionary {
// Archived classes need extra information not needed by traditionally loaded classes.
// To keep footprint small, we add these in the dictionary entry instead of the InstanceKlass.
class SharedDictionaryEntry : public DictionaryEntry {
public:
static void initialize(TRAPS) {}
static InstanceKlass* find_or_load_shared_class(Symbol* class_name,
Handle class_loader,
TRAPS) {
return NULL;
}
static void roots_oops_do(OopClosure* blk) {}
static void oops_do(OopClosure* f) {}
static bool is_sharing_possible(ClassLoaderData* loader_data) {
oop class_loader = loader_data->class_loader();
return (class_loader == NULL);
}
static bool is_shared_class_visible_for_classloader(
InstanceKlass* ik,
Handle class_loader,
const char* pkg_string,
Symbol* pkg_name,
PackageEntry* pkg_entry,
ModuleEntry* mod_entry,
TRAPS) {
return false;
enum LoaderType {
LT_BUILTIN,
LT_UNREGISTERED
};
enum {
FROM_FIELD_IS_PROTECTED = 1 << 0,
FROM_IS_ARRAY = 1 << 1,
FROM_IS_OBJECT = 1 << 2
};
int _id;
int _clsfile_size;
int _clsfile_crc32;
void* _verifier_constraints; // FIXME - use a union here to avoid type casting??
void* _verifier_constraint_flags;
// See "Identifying the loader_type of archived classes" comments above.
LoaderType loader_type() const {
Klass* k = (Klass*)literal();
if ((k->shared_classpath_index() != UNREGISTERED_INDEX)) {
return LT_BUILTIN;
} else {
return LT_UNREGISTERED;
}
}
SharedDictionaryEntry* next() {
return (SharedDictionaryEntry*)(DictionaryEntry::next());
}
bool is_builtin() const {
return loader_type() == LT_BUILTIN;
}
bool is_unregistered() const {
return loader_type() == LT_UNREGISTERED;
}
void add_verification_constraint(Symbol* name,
Symbol* from_name, bool from_field_is_protected, bool from_is_array, bool from_is_object);
int finalize_verification_constraints();
void check_verification_constraints(InstanceKlass* klass, TRAPS);
void metaspace_pointers_do(MetaspaceClosure* it) NOT_CDS_RETURN;
};
class SharedDictionary : public Dictionary {
SharedDictionaryEntry* get_entry_for_builtin_loader(const Symbol* name) const;
SharedDictionaryEntry* get_entry_for_unregistered_loader(const Symbol* name,
int clsfile_size,
int clsfile_crc32) const;
// Convenience functions
SharedDictionaryEntry* bucket(int index) const {
return (SharedDictionaryEntry*)(Dictionary::bucket(index));
}
public:
SharedDictionaryEntry* find_entry_for(Klass* klass);
void finalize_verification_constraints();
bool add_non_builtin_klass(const Symbol* class_name,
ClassLoaderData* loader_data,
InstanceKlass* obj);
void update_entry(Klass* klass, int id);
Klass* find_class_for_builtin_loader(const Symbol* name) const;
Klass* find_class_for_unregistered_loader(const Symbol* name,
int clsfile_size,
int clsfile_crc32) const;
bool class_exists_for_unregistered_loader(const Symbol* name) {
return (get_entry_for_unregistered_loader(name, -1, -1) != NULL);
}
};
class SystemDictionaryShared: public SystemDictionary {
private:
// These _shared_xxxs arrays are used to initialize the java.lang.Package and
// java.security.ProtectionDomain objects associated with each shared class.
//
// See SystemDictionaryShared::init_security_info for more info.
static objArrayOop _shared_protection_domains;
static objArrayOop _shared_jar_urls;
static objArrayOop _shared_jar_manifests;
static InstanceKlass* load_shared_class_for_builtin_loader(
Symbol* class_name,
Handle class_loader,
TRAPS);
static Handle get_package_name(Symbol* class_name, TRAPS);
// Package handling:
//
// 1. For named modules in the runtime image
// BOOT classes: Reuses the existing JVM_GetSystemPackage(s) interfaces
// to get packages in named modules for shared classes.
// Package for non-shared classes in named module is also
// handled using JVM_GetSystemPackage(s).
//
// APP classes: VM calls ClassLoaders.AppClassLoader::definePackage(String, Module)
// to define package for shared app classes from named
// modules.
//
// PLATFORM classes: VM calls ClassLoaders.PlatformClassLoader::definePackage(String, Module)
// to define package for shared platform classes from named
// modules.
//
// 2. For unnamed modules
// BOOT classes: Reuses the existing JVM_GetSystemPackage(s) interfaces to
// get packages for shared boot classes in unnamed modules.
//
// APP classes: VM calls ClassLoaders.AppClassLoader::defineOrCheckPackage()
// with with the manifest and url from archived data.
//
// PLATFORM classes: No package is defined.
//
// The following two define_shared_package() functions are used to define
// package for shared APP and PLATFORM classes.
static void define_shared_package(Symbol* class_name,
Handle class_loader,
Handle manifest,
Handle url,
TRAPS);
static void define_shared_package(Symbol* class_name,
Handle class_loader,
ModuleEntry* mod_entry,
TRAPS);
static Handle get_shared_jar_manifest(int shared_path_index, TRAPS);
static Handle get_shared_jar_url(int shared_path_index, TRAPS);
static Handle get_protection_domain_from_classloader(Handle class_loader,
Handle url, TRAPS);
static Handle get_shared_protection_domain(Handle class_loader,
int shared_path_index,
Handle url,
TRAPS);
static Handle get_shared_protection_domain(Handle class_loader,
ModuleEntry* mod, TRAPS);
static Handle init_security_info(Handle class_loader, InstanceKlass* ik, TRAPS);
static void atomic_set_array_index(objArrayOop array, int index, oop o) {
// Benign race condition: array.obj_at(index) may already be filled in.
// The important thing here is that all threads pick up the same result.
// It doesn't matter which racing thread wins, as long as only one
// result is used by all threads, and all future queries.
array->atomic_compare_exchange_oop(index, o, NULL);
}
static oop shared_protection_domain(int index);
static void atomic_set_shared_protection_domain(int index, oop pd) {
atomic_set_array_index(_shared_protection_domains, index, pd);
}
static void allocate_shared_protection_domain_array(int size, TRAPS);
static oop shared_jar_url(int index);
static void atomic_set_shared_jar_url(int index, oop url) {
atomic_set_array_index(_shared_jar_urls, index, url);
}
static void allocate_shared_jar_url_array(int size, TRAPS);
static oop shared_jar_manifest(int index);
static void atomic_set_shared_jar_manifest(int index, oop man) {
atomic_set_array_index(_shared_jar_manifests, index, man);
}
static void allocate_shared_jar_manifest_array(int size, TRAPS);
static InstanceKlass* acquire_class_for_current_thread(
InstanceKlass *ik,
Handle class_loader,
Handle protection_domain,
TRAPS);
public:
static void initialize(TRAPS);
// Called by PLATFORM/APP loader only
static InstanceKlass* find_or_load_shared_class(Symbol* class_name,
Handle class_loader,
TRAPS);
static void allocate_shared_data_arrays(int size, TRAPS);
static void oops_do(OopClosure* f);
static void roots_oops_do(OopClosure* f) {
oops_do(f);
}
// Check if sharing is supported for the class loader.
static bool is_sharing_possible(ClassLoaderData* loader_data) {
oop class_loader = loader_data->class_loader();
return (class_loader == NULL ||
(UseAppCDS && (SystemDictionary::is_system_class_loader(class_loader) ||
SystemDictionary::is_platform_class_loader(class_loader)))
);
}
static bool is_shared_class_visible_for_classloader(InstanceKlass* ik,
Handle class_loader,
const char* pkg_string,
Symbol* pkg_name,
PackageEntry* pkg_entry,
ModuleEntry* mod_entry,
TRAPS);
static PackageEntry* get_package_entry(Symbol* pkg,
ClassLoaderData *loader_data) {
if (loader_data != NULL) {
PackageEntryTable* pkgEntryTable = loader_data->packages();
return pkgEntryTable->lookup_only(pkg);
}
return NULL;
}
static bool add_non_builtin_klass(Symbol* class_name, ClassLoaderData* loader_data,
InstanceKlass* k, TRAPS);
static Klass* dump_time_resolve_super_or_fail(Symbol* child_name,
Symbol* class_name,
Handle class_loader,
Handle protection_domain,
bool is_superclass,
TRAPS) {
return NULL;
}
TRAPS);
static size_t dictionary_entry_size() {
return sizeof(DictionaryEntry);
return (DumpSharedSpaces) ? sizeof(SharedDictionaryEntry) : sizeof(DictionaryEntry);
}
static void init_shared_dictionary_entry(Klass* k, DictionaryEntry* entry) NOT_CDS_RETURN;
static bool is_builtin(DictionaryEntry* ent) {
// Can't use virtual function is_builtin because DictionaryEntry doesn't initialize
// vtable because it's not constructed properly.
SharedDictionaryEntry* entry = (SharedDictionaryEntry*)ent;
return entry->is_builtin();
}
static void init_shared_dictionary_entry(Klass* k, DictionaryEntry* entry) {}
static bool is_builtin(DictionaryEntry* entry) { return true; }
// For convenient access to the SharedDictionaryEntry's of the archived classes.
static SharedDictionary* shared_dictionary() {
assert(!DumpSharedSpaces, "not for dumping");
return (SharedDictionary*)SystemDictionary::shared_dictionary();
}
static InstanceKlass* lookup_from_stream(Symbol* class_name,
static SharedDictionary* boot_loader_dictionary() {
return (SharedDictionary*)ClassLoaderData::the_null_class_loader_data()->dictionary();
}
static void update_shared_entry(Klass* klass, int id) {
assert(DumpSharedSpaces, "sanity");
assert((SharedDictionary*)(klass->class_loader_data()->dictionary()) != NULL, "sanity");
((SharedDictionary*)(klass->class_loader_data()->dictionary()))->update_entry(klass, id);
}
static void set_shared_class_misc_info(Klass* k, ClassFileStream* cfs);
static InstanceKlass* lookup_from_stream(const Symbol* class_name,
Handle class_loader,
Handle protection_domain,
const ClassFileStream* st,
TRAPS) {
return NULL;
}
// The (non-application) CDS implementation supports only classes in the boot
// class loader, which ensures that the verification constraints are the same
// during archive creation time and runtime. Thus we can do the constraint checks
// entirely during archive creation time.
TRAPS);
// "verification_constraints" are a set of checks performed by
// VerificationType::is_reference_assignable_from when verifying a shared class during
// dump time.
//
// With AppCDS, it is possible to override archived classes by calling
// ClassLoader.defineClass() directly. SystemDictionary::load_shared_class() already
// ensures that you cannot load a shared class if its super type(s) are changed. However,
// we need an additional check to ensure that the verification_constraints did not change
// between dump time and runtime.
static bool add_verification_constraint(Klass* k, Symbol* name,
Symbol* from_name, bool from_field_is_protected,
bool from_is_array, bool from_is_object) {return false;}
static void finalize_verification_constraints() {}
bool from_is_array, bool from_is_object) NOT_CDS_RETURN_(false);
static void finalize_verification_constraints() NOT_CDS_RETURN;
static void check_verification_constraints(InstanceKlass* klass,
TRAPS) {}
};
class SharedDictionaryEntry : public DictionaryEntry {
public:
void metaspace_pointers_do(MetaspaceClosure* it) {}
TRAPS) NOT_CDS_RETURN;
};
#endif // SHARE_VM_CLASSFILE_SYSTEMDICTIONARYSHARED_HPP

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2017 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
@ -25,6 +25,17 @@
#ifndef SHARE_VM_CLASSFILE_SYSTEMDICTIONARY_EXT_HPP
#define SHARE_VM_CLASSFILE_SYSTEMDICTIONARY_EXT_HPP
#if INCLUDE_CDS
#define WK_KLASSES_DO_EXT(do_klass) \
/* well-known classes */ \
do_klass(jdk_internal_loader_ClassLoaders_klass, jdk_internal_loader_ClassLoaders, Pre ) \
/*end*/
#else
#define WK_KLASSES_DO_EXT(do_klass)
#endif // INCLUDE_CDS
#endif // SHARE_VM_CLASSFILE_SYSTEMDICTIONARY_EXT_HPP

View File

@ -26,7 +26,6 @@
#define SHARE_VM_CLASSFILE_VMSYMBOLS_HPP
#include "classfile/moduleEntry.hpp"
#include "classfile/vmSymbols_ext.hpp"
#include "oops/symbol.hpp"
#include "memory/iterator.hpp"
#include "trace/traceMacros.hpp"
@ -673,8 +672,12 @@
/* trace signatures */ \
TRACE_TEMPLATES(template) \
\
/* extensions */ \
VM_SYMBOLS_DO_EXT(template, do_alias) \
/* cds */ \
template(jdk_internal_loader_ClassLoaders, "jdk/internal/loader/ClassLoaders") \
template(jdk_vm_cds_SharedClassInfo, "jdk/vm/cds/SharedClassInfo") \
template(url_void_signature, "(Ljava/net/URL;)V") \
template(toFileURL_name, "toFileURL") \
template(toFileURL_signature, "(Ljava/lang/String;)Ljava/net/URL;") \
\
/*end*/

View File

@ -0,0 +1,69 @@
/*
* Copyright (c) 2014, 2017, 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/macros.hpp"
#if INCLUDE_CDS
#include "runtime/os.hpp"
#include "memory/filemap.hpp"
#include "memory/allocation.hpp"
#include "memory/allocation.inline.hpp"
#include "prims/cdsoffsets.hpp"
CDSOffsets* CDSOffsets::_all = NULL;
#define ADD_NEXT(list, name, value) \
list->add_end(new CDSOffsets(name, value, NULL))
#define CREATE_OFFSET_MAPS \
_all = new CDSOffsets("size_t_size", sizeof(size_t), NULL); \
ADD_NEXT(_all, "FileMapHeader::_magic", offset_of(FileMapInfo::FileMapHeader, _magic)); \
ADD_NEXT(_all, "FileMapHeader::_crc", offset_of(FileMapInfo::FileMapHeader, _crc)); \
ADD_NEXT(_all, "FileMapHeader::_version", offset_of(FileMapInfo::FileMapHeader, _version)); \
ADD_NEXT(_all, "FileMapHeader::_space[0]", offset_of(FileMapInfo::FileMapHeader, _space)); \
ADD_NEXT(_all, "space_info::_crc", offset_of(FileMapInfo::FileMapHeader::space_info, _crc)); \
ADD_NEXT(_all, "space_info::_used", offset_of(FileMapInfo::FileMapHeader::space_info, _used)); \
ADD_NEXT(_all, "FileMapHeader::_paths_misc_info_size", offset_of(FileMapInfo::FileMapHeader, _paths_misc_info_size)); \
ADD_NEXT(_all, "file_header_size", sizeof(FileMapInfo::FileMapHeader)); \
ADD_NEXT(_all, "space_info_size", sizeof(FileMapInfo::FileMapHeader::space_info));
int CDSOffsets::find_offset(const char* name) {
if (_all == NULL) {
CREATE_OFFSET_MAPS
}
CDSOffsets* it = _all;
while(it) {
if (!strcmp(name, it->get_name())) {
return it->get_offset();
}
it = it->next();
}
return -1; // not found
}
void CDSOffsets::add_end(CDSOffsets* n) {
CDSOffsets* p = this;
while(p && p->_next) { p = p->_next; }
p->_next = n;
}
#endif // INCLUDE_CDS

View File

@ -0,0 +1,48 @@
/*
* Copyright (c) 2014, 2017, 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_PRIMS_CDSOFFSETS_HPP
#define SHARE_PRIMS_CDSOFFSETS_HPP
class CDSOffsets: public CHeapObj<mtInternal> {
private:
char* _name;
int _offset;
CDSOffsets* _next;
static CDSOffsets* _all; // sole list for cds
public:
CDSOffsets(const char* name, int offset, CDSOffsets* next) {
_name = NEW_C_HEAP_ARRAY(char, strlen(name) + 1, mtInternal);
strcpy(_name, name);
_offset = offset;
_next = next;
}
char* get_name() const { return _name; }
int get_offset() const { return _offset; }
CDSOffsets* next() const { return _next; }
void add_end(CDSOffsets* n);
static int find_offset(const char* name);
};
#endif // SHARE_PRIMS_CDSOFFSETS_HPP

View File

@ -61,6 +61,9 @@
#include "utilities/debug.hpp"
#include "utilities/exceptions.hpp"
#include "utilities/macros.hpp"
#if INCLUDE_CDS
#include "prims/cdsoffsets.hpp"
#endif // INCLUDE_CDS
#if INCLUDE_ALL_GCS
#include "gc/g1/concurrentMarkThread.hpp"
#include "gc/g1/g1CollectedHeap.inline.hpp"
@ -1730,6 +1733,18 @@ WB_ENTRY(jboolean, WB_IsCDSIncludedInVmBuild(JNIEnv* env))
#endif
WB_END
#if INCLUDE_CDS
WB_ENTRY(jint, WB_GetOffsetForName(JNIEnv* env, jobject o, jstring name))
ResourceMark rm;
char* c_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(name));
int result = CDSOffsets::find_offset(c_name);
return (jint)result;
WB_END
#endif // INCLUDE_CDS
WB_ENTRY(jint, WB_HandshakeWalkStack(JNIEnv* env, jobject wb, jobject thread_handle, jboolean all_threads))
class TraceSelfClosure : public ThreadClosure {
jint _num_threads_completed;
@ -1918,6 +1933,9 @@ static JNINativeMethod methods[] = {
{CC"runMemoryUnitTests", CC"()V", (void*)&WB_RunMemoryUnitTests},
{CC"readFromNoaccessArea",CC"()V", (void*)&WB_ReadFromNoaccessArea},
{CC"stressVirtualSpaceResize",CC"(JJJ)I", (void*)&WB_StressVirtualSpaceResize},
#if INCLUDE_CDS
{CC"getOffsetForName0", CC"(Ljava/lang/String;)I", (void*)&WB_GetOffsetForName},
#endif
#if INCLUDE_ALL_GCS
{CC"g1InConcurrentMark", CC"()Z", (void*)&WB_G1InConcurrentMark},
{CC"g1IsHumongous0", CC"(Ljava/lang/Object;)Z", (void*)&WB_G1IsHumongous },

View File

@ -3880,6 +3880,14 @@ jint Arguments::match_special_option_and_act(const JavaVMInitArgs* args,
vm_exit(0);
}
#endif
if (match_option(option, "-XX:+UseAppCDS")) {
Flag* flag = Flag::find_flag("SharedArchiveFile", 17, true, true);
if (flag->is_diagnostic()) {
flag->clear_diagnostic();
}
continue;
}
}
return JNI_OK;
}

View File

@ -36,7 +36,6 @@ public:
// Otherwise returns false.
static inline bool process_options(const JavaVMOption *option) { return false; }
static inline void report_unsupported_options() { }
static inline bool using_AppCDS() { return false; }
};
void ArgumentsExt::set_gc_specific_flags() {

View File

@ -3932,6 +3932,13 @@ public:
"Address to allocate shared memory region for class data") \
range(0, SIZE_MAX) \
\
product(bool, UseAppCDS, false, \
"Enable Application Class Data Sharing when using shared spaces") \
writeable(CommandLineOnly) \
\
product(ccstr, SharedArchiveConfigFile, NULL, \
"Data to add to the CDS archive file") \
\
product(uintx, SharedSymbolTableBucketSize, 4, \
"Average number of symbols per bucket in shared table") \
range(2, 246) \

View File

@ -189,12 +189,27 @@ hotspot_tier1_runtime = \
-runtime/Unsafe/RangeCheck.java \
-runtime/containers/ \
sanity/ \
testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java
testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java \
-:hotspot_tier1_runtime_appcds_exclude
hotspot_cds = \
runtime/SharedArchiveFile/ \
runtime/CompressedOops/
# AppCDS
# If modifying AppCDS it is also recommended to run the open hotspot_cds group
hotspot_appcds = \
runtime/appcds/
# A subset of AppCDS tests to be run in JPRT push
hotspot_tier1_runtime_appcds = \
runtime/appcds/HelloTest.java \
runtime/appcds/sharedStrings/SharedStringsBasic.java \
runtime/appcds/ClassLoaderTest.java
hotspot_tier1_runtime_appcds_exclude = \
runtime/appcds/ \
-:hotspot_tier1_runtime_appcds
hotspot_tier1_serviceability = \
serviceability/dcmd/compiler \

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2017, 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.
*
*/
import jdk.test.lib.cds.CDSOptions;
// This class represents options used for
// during creation of the archive and/or running JVM with archive
public class AppCDSOptions extends CDSOptions {
public String appJar;
// Application classes to be archived
public String[] appClasses;
public AppCDSOptions setAppJar(String appJar) {
this.appJar = appJar;
return this;
}
public AppCDSOptions setAppClasses(String[] appClasses) {
this.appClasses = appClasses;
return this;
}
}

View File

@ -0,0 +1,87 @@
/*
* Copyright (c) 2014, 2017, 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
* @summary At run time, it is OK to append new elements to the classpath that was used at dump time.
* AppCDS does not support uncompressed oops
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @compile test-classes/Hello.java
* @compile test-classes/HelloMore.java
* @run main AppendClasspath
*/
import java.io.File;
import jdk.test.lib.process.OutputAnalyzer;
public class AppendClasspath {
public static void main(String[] args) throws Exception {
String appJar = JarBuilder.getOrCreateHelloJar();
String appJar2 = JarBuilder.build("AppendClasspath_HelloMore", "HelloMore");
// Dump an archive with a specified JAR file in -classpath
TestCommon.testDump(appJar, TestCommon.list("Hello"));
// PASS: 1) runtime with classpath containing the one used in dump time
OutputAnalyzer output = TestCommon.execCommon(
"-cp", appJar + File.pathSeparator + appJar2,
"HelloMore");
TestCommon.checkExec(output);
final String errorMessage1 = "Unable to use shared archive";
final String errorMessage2 = "shared class paths mismatch";
// FAIL: 2) runtime with classpath different from the one used in dump time
// (runtime has an extra jar file prepended to the class path)
output = TestCommon.execCommon(
"-cp", appJar2 + File.pathSeparator + appJar,
"HelloMore");
output.shouldContain(errorMessage1);
output.shouldContain(errorMessage2);
output.shouldHaveExitValue(1);
// FAIL: 3) runtime with classpath part of the one used in dump time
TestCommon.testDump(appJar + File.pathSeparator + appJar2,
TestCommon.list("Hello"));
output = TestCommon.execCommon(
"-cp", appJar2,
"Hello");
output.shouldContain(errorMessage1);
output.shouldContain(errorMessage2);
output.shouldHaveExitValue(1);
// FAIL: 4) runtime with same set of jar files in the classpath but
// with different order
output = TestCommon.execCommon(
"-cp", appJar2 + File.pathSeparator + appJar,
"HelloMore");
output.shouldContain(errorMessage1);
output.shouldContain(errorMessage2);
output.shouldHaveExitValue(1);
}
}

View File

@ -0,0 +1,108 @@
/*
* Copyright (c) 2014, 2017, 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
* @summary bootclasspath mismatch test.
* AppCDS does not support uncompressed oops
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @compile test-classes/Hello.java
* @run main BootClassPathMismatch
*/
import jdk.test.lib.process.OutputAnalyzer;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.StandardCopyOption;
import java.nio.file.Paths;
public class BootClassPathMismatch {
private static final String mismatchMessage = "shared class paths mismatch";
public static void main(String[] args) throws Exception {
JarBuilder.getOrCreateHelloJar();
copyHelloToNewDir();
BootClassPathMismatch test = new BootClassPathMismatch();
test.testBootClassPathMismatch();
test.testBootClassPathMatch();
}
/* Error should be detected if:
* dump time: -Xbootclasspath/a:${testdir}/hello.jar
* run-time : -Xbootclasspath/a:${testdir}/newdir/hello.jar
*/
public void testBootClassPathMismatch() throws Exception {
String appJar = JarBuilder.getOrCreateHelloJar();
String appClasses[] = {"Hello"};
OutputAnalyzer dumpOutput = TestCommon.dump(
appJar, appClasses, "-Xbootclasspath/a:" + appJar);
String testDir = TestCommon.getTestDir("newdir");
String otherJar = testDir + File.separator + "hello.jar";
OutputAnalyzer execOutput = TestCommon.exec(
appJar, "-verbose:class", "-Xbootclasspath/a:" + otherJar, "Hello");
try {
TestCommon.checkExec(execOutput, mismatchMessage);
} catch (java.lang.RuntimeException re) {
String cause = re.getMessage();
if (!mismatchMessage.equals(cause)) {
throw re;
}
}
}
/* No error if:
* dump time: -Xbootclasspath/a:${testdir}/hello.jar
* run-time : -Xbootclasspath/a:${testdir}/hello.jar
*/
public void testBootClassPathMatch() throws Exception {
String appJar = TestCommon.getTestJar("hello.jar");
String appClasses[] = {"Hello"};
OutputAnalyzer dumpOutput = TestCommon.dump(
appJar, appClasses, "-Xbootclasspath/a:" + appJar);
OutputAnalyzer execOutput = TestCommon.exec(
appJar, "-verbose:class",
"-Xbootclasspath/a:" + appJar, "Hello");
TestCommon.checkExec(execOutput,
"[class,load] Hello source: shared objects file");
}
private static void copyHelloToNewDir() throws Exception {
String classDir = System.getProperty("test.classes");
String dstDir = classDir + File.separator + "newdir";
try {
Files.createDirectory(Paths.get(dstDir));
} catch (FileAlreadyExistsException e) { }
Files.copy(Paths.get(classDir, "hello.jar"),
Paths.get(dstDir, "hello.jar"),
StandardCopyOption.REPLACE_EXISTING);
}
}

View File

@ -0,0 +1,92 @@
/*
* Copyright (c) 2016, 2017, 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
* @summary Test case sensitive aspect of comparing class paths
* between dump time and archive use time
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @requires os.family != "mac"
* @compile test-classes/Hello.java
* @run main CaseSensitiveClassPath
*/
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import jdk.test.lib.Platform;
import jdk.test.lib.process.OutputAnalyzer;
// Excluded from running on MAC: a more comprehensive case sensitivity detection
// and fix mechanism is needed, which is planned to be implemented in the future.
public class CaseSensitiveClassPath {
public static void main(String[] args) throws Exception {
String appJar = JarBuilder.getOrCreateHelloJar();
String appJarUpper = appJar.replace("hello", "Hello");
OutputAnalyzer out = TestCommon.dump(appJar, TestCommon.list("Hello"));
TestCommon.checkDump(out);
Path jarPath = Paths.get(appJar);
Path jarPathUpper = null;
boolean fileExists = false;
try {
jarPathUpper = Files.createFile(Paths.get(appJarUpper));
} catch (FileAlreadyExistsException faee) {
fileExists = true;
}
if (!fileExists) {
try {
Files.copy(jarPath, jarPathUpper, StandardCopyOption.REPLACE_EXISTING);
} catch (Exception e) {
throw new java.lang.RuntimeException(
"Failed copying file from " + appJar + " to " + appJarUpper + ".", e);
}
} else {
jarPathUpper = Paths.get(appJarUpper);
}
out = TestCommon.exec(appJarUpper, "Hello", "-Xlog:class+path=info",
"-Xlog:cds");
if (TestCommon.isUnableToMap(out))
return;
if (Files.isSameFile(jarPath, jarPathUpper)) {
TestCommon.checkExec(out, "Hello World");
} else {
out.shouldContain("shared class paths mismatch")
.shouldHaveExitValue(1);
}
}
}

View File

@ -0,0 +1,93 @@
/*
* Copyright (c) 2014, 2017, 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
* @summary Initiating and defining classloader test.
* AppCDS does not support uncompressed oops
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @compile test-classes/Hello.java
* @compile test-classes/HelloWB.java
* @compile test-classes/ForNameTest.java
* @compile test-classes/BootClassPathAppendHelper.java
* @build sun.hotspot.WhiteBox
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* @run main ClassLoaderTest
*/
import java.io.File;
import jdk.test.lib.process.OutputAnalyzer;
public class ClassLoaderTest {
public static void main(String[] args) throws Exception {
JarBuilder.build(true, "ClassLoaderTest-WhiteBox", "sun/hotspot/WhiteBox");
JarBuilder.getOrCreateHelloJar();
JarBuilder.build("ClassLoaderTest-HelloWB", "HelloWB");
JarBuilder.build("ClassLoaderTest-ForName", "ForNameTest");
ClassLoaderTest test = new ClassLoaderTest();
test.testBootLoader();
test.testDefiningLoader();
}
public void testBootLoader() throws Exception {
String appJar = TestCommon.getTestJar("ClassLoaderTest-HelloWB.jar");
String appClasses[] = {"HelloWB"};
String whiteBoxJar = TestCommon.getTestJar("ClassLoaderTest-WhiteBox.jar");
String bootClassPath = "-Xbootclasspath/a:" + appJar +
File.pathSeparator + whiteBoxJar;
TestCommon.dump(appJar, appClasses, bootClassPath);
OutputAnalyzer runtimeOutput = TestCommon.execCommon(
"-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI",
"-cp", appJar, bootClassPath, "-Xlog:class+load", "HelloWB");
if (!TestCommon.isUnableToMap(runtimeOutput)) {
runtimeOutput.shouldNotContain(
"[class,load] HelloWB source: shared objects file by jdk/internal/misc/ClassLoaders$AppClassLoader");
runtimeOutput.shouldContain("[class,load] HelloWB source: shared objects file");
}
}
public void testDefiningLoader() throws Exception {
// The boot loader should be used to load the class when it's
// on the bootclasspath, regardless who is the initiating classloader.
// In this test case, the AppClassLoader is the initiating classloader.
String helloJar = TestCommon.getTestJar("hello.jar");
String appJar = helloJar + System.getProperty("path.separator") +
TestCommon.getTestJar("ClassLoaderTest-ForName.jar");
String whiteBoxJar = TestCommon.getTestJar("ClassLoaderTest-WhiteBox.jar");
String bootClassPath = "-Xbootclasspath/a:" + helloJar +
File.pathSeparator + whiteBoxJar;
TestCommon.dump(helloJar, TestCommon.list("Hello"), bootClassPath);
TestCommon.execCommon("-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI",
"-cp", appJar, bootClassPath, "-XX:+TraceClassPaths", "ForNameTest");
}
}

View File

@ -0,0 +1,106 @@
/*
* Copyright (c) 2014, 2017, 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
* @summary Class-Path: attribute in MANIFEST file
* AppCDS does not support uncompressed oops
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @run main ClassPathAttr
*/
import jdk.test.lib.process.OutputAnalyzer;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.StandardCopyOption;
import java.nio.file.Paths;
public class ClassPathAttr {
public static void main(String[] args) throws Exception {
buildCpAttr("cpattr1", "cpattr1.mf", "CpAttr1", "CpAttr1");
buildCpAttr("cpattr1_long", "cpattr1_long.mf", "CpAttr1", "CpAttr1");
buildCpAttr("cpattr2", "cpattr2.mf", "CpAttr2", "CpAttr2");
buildCpAttr("cpattr3", "cpattr3.mf", "CpAttr3", "CpAttr2", "CpAttr3");
buildCpAttr("cpattr4", "cpattr4.mf", "CpAttr4",
"CpAttr2", "CpAttr3", "CpAttr4", "CpAttr5");
buildCpAttr("cpattr5_123456789_223456789_323456789_423456789_523456789_623456789", "cpattr5_extra_long.mf", "CpAttr5", "CpAttr5");
for (int i=1; i<=2; i++) {
String jar1 = TestCommon.getTestJar("cpattr1.jar");
String jar4 = TestCommon.getTestJar("cpattr4.jar");
if (i == 2) {
// Test case #2 -- same as #1, except we use cpattr1_long.jar, which has a super-long
// Class-Path: attribute.
jar1 = TestCommon.getTestJar("cpattr1_long.jar");
}
String cp = jar1 + File.pathSeparator + jar4;
TestCommon.testDump(cp, TestCommon.list("CpAttr1",
"CpAttr2",
"CpAttr3",
"CpAttr4",
"CpAttr5"));
OutputAnalyzer output = TestCommon.execCommon(
"-cp", cp,
"CpAttr1");
TestCommon.checkExec(output);
// Logging test for class+path.
output = TestCommon.execCommon(
"-Xlog:class+path",
"-cp", cp,
"CpAttr1");
if (!TestCommon.isUnableToMap(output)){
output.shouldMatch("checking shared classpath entry: .*cpattr2.jar");
output.shouldMatch("checking shared classpath entry: .*cpattr3.jar");
}
// Make sure aliased TraceClassPaths still works
output = TestCommon.execCommon(
"-XX:+TraceClassPaths",
"-cp", cp,
"CpAttr1");
if (!TestCommon.isUnableToMap(output)){
output.shouldMatch("checking shared classpath entry: .*cpattr2.jar");
output.shouldMatch("checking shared classpath entry: .*cpattr3.jar");
}
}
}
private static void buildCpAttr(String jarName, String manifest, String enclosingClassName, String ...testClassNames) throws Exception {
String jarClassesDir = System.getProperty("test.classes") + File.separator + jarName + "_classes";
try { Files.createDirectory(Paths.get(jarClassesDir)); } catch (FileAlreadyExistsException e) { }
JarBuilder.compile(jarClassesDir, System.getProperty("test.src") + File.separator +
"test-classes" + File.separator + enclosingClassName + ".java");
JarBuilder.buildWithManifest(jarName, manifest, jarClassesDir, testClassNames);
}
}

View File

@ -0,0 +1,128 @@
/*
* Copyright (c) 2014, 2017, 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 CommandLineFlagCombo
* AppCDS does not support uncompressed oops
* @requires (vm.gc=="null") & ((vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true))
* @summary Test command line flag combinations that
* could likely affect the behaviour of AppCDS
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @compile test-classes/Hello.java
* @run main/timeout=240 CommandLineFlagCombo
*/
import jdk.test.lib.BuildHelper;
import jdk.test.lib.Platform;
import jdk.test.lib.process.OutputAnalyzer;
public class CommandLineFlagCombo {
// shared base address test table
private static final String[] testTable = {
"-XX:+UseG1GC", "-XX:+UseSerialGC", "-XX:+UseParallelGC", "-XX:+UseConcMarkSweepGC",
"-XX:+FlightRecorder",
"-XX:+UseLargePages", // may only take effect on machines with large-pages
"-XX:+UseCompressedClassPointers",
"-XX:+UseCompressedOops",
"-XX:ObjectAlignmentInBytes=16",
"-XX:ObjectAlignmentInBytes=32",
"-XX:ObjectAlignmentInBytes=64"
};
public static void main(String[] args) throws Exception {
String appJar = JarBuilder.getOrCreateHelloJar();
String classList[] = {"Hello"};
for (String testEntry : testTable) {
System.out.println("CommandLineFlagCombo = " + testEntry);
if (skipTestCase(testEntry))
continue;
OutputAnalyzer dumpOutput;
if (testEntry.equals("-XX:+FlightRecorder")) {
dumpOutput = TestCommon.dump(appJar, classList, "-XX:+UnlockCommercialFeatures", testEntry);
} else {
dumpOutput = TestCommon.dump(appJar, classList, testEntry);
}
TestCommon.checkDump(dumpOutput, "Loading classes to share");
OutputAnalyzer execOutput;
if (testEntry.equals("-XX:+FlightRecorder")) {
execOutput = TestCommon.exec(appJar, "-XX:+UnlockCommercialFeatures", testEntry, "Hello");
} else {
execOutput = TestCommon.exec(appJar, testEntry, "Hello");
}
TestCommon.checkExec(execOutput, "Hello World");
}
for (int i=0; i<2; i++) {
String g1Flag, serialFlag;
// Interned strings are supported only with G1GC. However, we should not crash if:
// 0: archive has shared strings, but run time doesn't support shared strings
// 1: archive has no shared strings, but run time supports shared strings
String dump_g1Flag = "-XX:" + (i == 0 ? "+" : "-") + "UseG1GC";
String run_g1Flag = "-XX:" + (i != 0 ? "+" : "-") + "UseG1GC";
String dump_serialFlag = "-XX:" + (i != 0 ? "+" : "-") + "UseSerialGC";
String run_serialFlag = "-XX:" + (i == 0 ? "+" : "-") + "UseSerialGC";
OutputAnalyzer dumpOutput = TestCommon.dump(
appJar, classList, dump_g1Flag, dump_serialFlag);
TestCommon.checkDump(dumpOutput, "Loading classes to share");
OutputAnalyzer execOutput = TestCommon.exec(appJar, run_g1Flag, run_serialFlag, "Hello");
TestCommon.checkExec(execOutput, "Hello World");
}
}
private static boolean skipTestCase(String testEntry) throws Exception {
if (Platform.is32bit())
{
if (testEntry.equals("-XX:+UseCompressedOops") ||
testEntry.equals("-XX:+UseCompressedClassPointers") ||
testEntry.contains("ObjectAlignmentInBytes") )
{
System.out.println("Test case not applicable on 32-bit platforms");
return true;
}
}
if (!BuildHelper.isCommercialBuild() && testEntry.equals("-XX:+FlightRecorder"))
{
System.out.println("Test case not applicable on non-commercial builds");
return true;
}
return false;
}
}

View File

@ -0,0 +1,101 @@
/*
* Copyright (c) 2014, 2017, 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 CommandLineFlagComboNegative
* @summary Test command line flag combinations that differ between
* the dump and execute steps, in such way that they cause errors
* E.g. use compressed oops for creating and archive, but then
* execute w/o compressed oops
* AppCDS does not support uncompressed oops
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @compile test-classes/Hello.java
* @run main CommandLineFlagComboNegative
*/
import java.util.ArrayList;
import jdk.test.lib.Platform;
import jdk.test.lib.process.OutputAnalyzer;
public class CommandLineFlagComboNegative {
private class TestVector {
public String testOptionForDumpStep;
public String testOptionForExecuteStep;
public String expectedErrorMsg;
public int expectedErrorCode;
public TestVector(String testOptionForDumpStep, String testOptionForExecuteStep,
String expectedErrorMsg, int expectedErrorCode) {
this.testOptionForDumpStep=testOptionForDumpStep;
this.testOptionForExecuteStep=testOptionForExecuteStep;
this.expectedErrorMsg=expectedErrorMsg;
this.expectedErrorCode=expectedErrorCode;
}
}
private ArrayList<TestVector> testTable = new ArrayList<TestVector>();
private void initTestTable() {
// These options are not applicable on 32-bit platforms
if (Platform.is64bit()) {
testTable.add( new TestVector("-XX:ObjectAlignmentInBytes=8", "-XX:ObjectAlignmentInBytes=16",
"An error has occurred while processing the shared archive file", 1) );
testTable.add( new TestVector("-XX:ObjectAlignmentInBytes=64", "-XX:ObjectAlignmentInBytes=32",
"An error has occurred while processing the shared archive file", 1) );
testTable.add( new TestVector("-XX:+UseCompressedOops", "-XX:-UseCompressedOops",
"Class data sharing is inconsistent with other specified options", 1) );
testTable.add( new TestVector("-XX:+UseCompressedClassPointers", "-XX:-UseCompressedClassPointers",
"Class data sharing is inconsistent with other specified options", 1) );
}
}
private void runTests() throws Exception
{
for (TestVector testEntry : testTable) {
System.out.println("CommandLineFlagComboNegative: dump = " + testEntry.testOptionForDumpStep);
System.out.println("CommandLineFlagComboNegative: execute = " + testEntry.testOptionForExecuteStep);
String appJar = JarBuilder.getOrCreateHelloJar();
OutputAnalyzer dumpOutput = TestCommon.dump(
appJar, new String[] {"Hello"}, testEntry.testOptionForDumpStep);
TestCommon.checkDump(dumpOutput, "Loading classes to share");
OutputAnalyzer execOutput = TestCommon.exec(appJar, testEntry.testOptionForExecuteStep, "Hello");
execOutput.shouldContain(testEntry.expectedErrorMsg);
execOutput.shouldHaveExitValue(testEntry.expectedErrorCode);
}
}
public static void main(String[] args) throws Exception {
CommandLineFlagComboNegative thisClass = new CommandLineFlagComboNegative();
thisClass.initTestTable();
thisClass.runTests();
}
}

View File

@ -0,0 +1,80 @@
/*
* Copyright (c) 2015, 2017, 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.
*
*/
import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import javax.tools.ToolProvider;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* This class consists exclusively of static utility methods for invoking the
* java compiler.
*
* This class will eventually move to jdk.testlibrary.
*/
public final class CompilerUtils {
private CompilerUtils() { }
/**
* Compile all the java sources in {@code <source>/**} to
* {@code <destination>/**}. The destination directory will be created if
* it doesn't exist.
*
* All warnings/errors emitted by the compiler are output to System.out/err.
*
* @return true if the compilation is successful
*
* @throws IOException if there is an I/O error scanning the source tree or
* creating the destination directory
*/
public static boolean compile(Path source, Path destination, String ... options)
throws IOException
{
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager jfm = compiler.getStandardFileManager(null, null, null);
List<Path> sources
= Files.find(source, Integer.MAX_VALUE,
(file, attrs) -> (file.toString().endsWith(".java")))
.collect(Collectors.toList());
Files.createDirectories(destination);
jfm.setLocationFromPaths(StandardLocation.CLASS_OUTPUT,
Arrays.asList(destination));
List<String> opts = Arrays.asList(options);
JavaCompiler.CompilationTask task
= compiler.getTask(null, jfm, null, opts, null,
jfm.getJavaFileObjectsFromPaths(sources));
return task.call();
}
}

View File

@ -0,0 +1,103 @@
/*
* Copyright (c) 2016, 2017, 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
* @summary DumpLoadedClassList should exclude generated classes, classes in bootclasspath/a and
* --patch-module.
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @library /test/lib
* @modules java.base/jdk.internal.misc
* jdk.jartool/sun.tools.jar
* @compile test-classes/ArrayListTest.java
* @run main DumpClassList
*/
import jdk.test.lib.compiler.InMemoryJavaCompiler;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
public class DumpClassList {
public static void main(String[] args) throws Exception {
// build The app
String[] appClass = new String[] {"ArrayListTest"};
String classList = "app.list";
JarBuilder.build("app", appClass[0]);
String appJar = TestCommon.getTestJar("app.jar");
// build patch-module
String source = "package java.lang; " +
"public class NewClass { " +
" static { " +
" System.out.println(\"NewClass\"); "+
" } " +
"}";
ClassFileInstaller.writeClassToDisk("java/lang/NewClass",
InMemoryJavaCompiler.compile("java.lang.NewClass", source, "--patch-module=java.base"),
System.getProperty("test.classes"));
String patchJar = JarBuilder.build("javabase", "java/lang/NewClass");
// build bootclasspath/a
String source2 = "package boot.append; " +
"public class Foo { " +
" static { " +
" System.out.println(\"Foo\"); " +
" } " +
"}";
ClassFileInstaller.writeClassToDisk("boot/append/Foo",
InMemoryJavaCompiler.compile("boot.append.Foo", source2),
System.getProperty("test.classes"));
String appendJar = JarBuilder.build("bootappend", "boot/append/Foo");
// dump class list
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
true,
"-XX:DumpLoadedClassList=" + classList,
"--patch-module=java.base=" + patchJar,
"-Xbootclasspath/a:" + appendJar,
"-cp",
appJar,
appClass[0]);
OutputAnalyzer output = TestCommon.executeAndLog(pb, "dumpClassList");
TestCommon.checkExecReturn(output, 0, true,
"hello world",
"skip writing class java/lang/NewClass") // skip classes outside of jrt image
.shouldNotContain("skip writing class boot/append/Foo"); // but classes on -Xbootclasspath/a should not be skipped
output = TestCommon.createArchive(appJar, appClass,
"-Xbootclasspath/a:" + appendJar,
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+PrintSystemDictionaryAtExit",
"-XX:SharedClassListFile=" + classList);
TestCommon.checkDump(output)
.shouldNotContain("Preload Warning: Cannot find java/lang/invoke/LambdaForm")
.shouldNotContain("Preload Warning: Cannot find boot/append/Foo")
.shouldContain("boot.append.Foo, loader <shared, not restored>");
}
}

View File

@ -0,0 +1,11 @@
VERSION: 1.0
@SECTION: Symbol
0 -1:
41 -1: (Ljava/util/Set<TE;>;Ljava/lang/Object;)V
11 -1 linkMethod
18 -1: type can't be null
20 -1: isAlphaNumericString
43 -1: (Ljava/lang/Class<*>;Ljava/lang/Class<*>;)Z
1 -1: \t
15 -1: IntCumulateTask
1 -1: \n

View File

@ -0,0 +1,5 @@
@SECTION: Symbol
20 -1: isAlphaNumericString
43 -1: (Ljava/lang/Class<*>;Ljava/lang/Class<*>;)Z
15 -1: IntCumulateTask
1 -1: \n

View File

@ -0,0 +1,13 @@
VERSION: 1.0
@SECTION: Symbol
11 -1: linkMethod
18 -1: isAlphaNumericString
33 -1: java/util/Locale$LocaleNameGetter
23 -1: sun/invoke/util/Wrapper
12 -1: reduceToLong
11 -1: setReadOnly
8 -1: endsWith
55 -1: <T:Ljava/lang/Object;>(Ljava/lang/ClassValue<TT;>;TT;)V
20 -1: createAnnotationData
6 -1: OfLong
17 -1: getClassSignature

View File

@ -0,0 +1,89 @@
/*
* Copyright (c) 2014, 2017, 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
* @summary Adding extra symbols into CDS archive using -XX:SharedArchiveConfigFile
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @compile test-classes/Hello.java
* @run main ExtraSymbols
*/
import java.io.*;
import jdk.test.lib.process.OutputAnalyzer;
public class ExtraSymbols {
public static void main(String[] args) throws Exception {
String appJar = JarBuilder.getOrCreateHelloJar();
// 1. Dump without extra symbols.
OutputAnalyzer output = TestCommon.dump(appJar, TestCommon.list("Hello"));
checkOutput(output);
int numEntries1 = numOfEntries(output);
// 2. Dump an archive with extra symbols. All symbols in
// ExtraSymbols.symbols.txt are valid. Dumping should succeed.
output = TestCommon.dump(appJar, TestCommon.list("Hello"),
"-XX:SharedArchiveConfigFile=" + TestCommon.getSourceFile("ExtraSymbols.symbols.txt"));
checkOutput(output);
int numEntries2 = numOfEntries(output);
if (numEntries2 <= numEntries1) {
throw new RuntimeException("No extra symbols added to archive");
}
output = TestCommon.exec(appJar, "Hello");
TestCommon.checkExec(output);
// 3. Dump with invalid symbol files. Dumping should fail.
String invalid_symbol_files[] = {"ExtraSymbols.invalid_1.txt",
"ExtraSymbols.invalid_2.txt",
"ExtraSymbols.invalid_3.txt"};
String err_msgs[] = {"Corrupted at line",
"wrong version of hashtable dump file",
"Corrupted at line"};
for (int i = 0; i < invalid_symbol_files.length; i++) {
output = TestCommon.dump(appJar, TestCommon.list("Hello"),
"-XX:SharedArchiveConfigFile=" +
TestCommon.getSourceFile(invalid_symbol_files[i]));
output.shouldContain("Error occurred during initialization of VM");
output.shouldContain(err_msgs[i]);
}
}
static int numOfEntries(OutputAnalyzer output) {
String s = output.firstMatch("Number of entries : .*");
String subs[] = s.split("[:]");
int numEntries = Integer.parseInt(subs[1].trim());
return numEntries;
}
static void checkOutput(OutputAnalyzer output) throws Exception {
output.shouldContain("Loading classes to share");
output.shouldContain("Shared symbol table stats -------- base:");
output.shouldHaveExitValue(0);
}
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,67 @@
/*
* Copyright (c) 2017, 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
* @summary Test for field annotations.
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @compile test-classes/FieldAnnotationsApp.java test-classes/MyAnnotation.java
* @run main FieldAnnotationsTest
*/
import jdk.test.lib.process.OutputAnalyzer;
// This is a test for the handling of multi-dimensional Arrays in MetaspaceClosure.
//
// We choose FieldAnnotations because they happen to be implemented as a multi-dimension
// Array (Annotations::_fields_annotations, which is of type Array<Array<unsigned char>*>*,
// and is handled by the template class PointerArrayRef<T> in metaspaceClosure.hpp).
//
// Specifically, we are testing the following C code, where _fields_annotations is non-NULL:
//
// void Annotations::metaspace_pointers_do(MetaspaceClosure* it) {
// ...
// it->push(&_fields_annotations);
//
// which will be matched with the function
//
// template <typename T> void MetaspaceClosure::push(Array<T*>** mpp, Writability w = _default)
//
public class FieldAnnotationsTest {
public static void main(String[] args) throws Exception {
String[] ARCHIVE_CLASSES = {"FieldAnnotationsApp", "MyAnnotation"};
String appJar = JarBuilder.build("FieldAnnotationsTest", ARCHIVE_CLASSES);
OutputAnalyzer dumpOutput = TestCommon.dump(
appJar, ARCHIVE_CLASSES);
TestCommon.checkDump(dumpOutput);
OutputAnalyzer execOutput = TestCommon.exec(appJar, "FieldAnnotationsApp");
TestCommon.checkExec(execOutput, "Field annotations are OK.");
}
}

View File

@ -0,0 +1,118 @@
/*
* Copyright (c) 2017, 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
* @summary Unused metadata created during dump time should be freed from the CDS archive.
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @library /test/lib
* @modules jdk.jartool/sun.tools.jar
* @compile test-classes/MethodNoReturn.jasm test-classes/Hello.java
* @run main FreeUnusedMetadata
*/
import java.nio.file.Files;
import java.nio.file.Paths;
import jdk.test.lib.process.OutputAnalyzer;
public class FreeUnusedMetadata {
static byte iconst_1 = 4;
static byte pop = 87;
static byte[] pattern = { // This has the same sequence as in test-classes/MethodNoReturn.jasm
iconst_1,
pop,
iconst_1,
pop,
iconst_1,
pop,
iconst_1,
pop,
iconst_1,
pop,
iconst_1,
pop,
iconst_1,
pop,
iconst_1,
pop,
iconst_1,
pop,
iconst_1,
pop,
iconst_1,
iconst_1,
iconst_1,
iconst_1,
iconst_1,
iconst_1,
iconst_1,
iconst_1,
pop,
pop,
pop,
pop,
pop,
pop,
pop,
pop
};
public static void main(String[] args) throws Exception {
String[] ARCHIVE_CLASSES = {"Hello", "MethodNoReturn"};
String appJar = JarBuilder.build("FreeUnusedMetadata", ARCHIVE_CLASSES);
OutputAnalyzer dumpOutput = TestCommon.dump(
appJar, ARCHIVE_CLASSES);
TestCommon.checkDump(dumpOutput, "Loading classes to share");
OutputAnalyzer execOutput = TestCommon.exec(appJar, "Hello");
TestCommon.checkExec(execOutput, "Hello World");
String archive = TestCommon.getCurrentArchiveName();
System.out.println("Checking for pattern inside " + archive + "...");
byte[] data = Files.readAllBytes(Paths.get(archive));
int max = data.length - pattern.length;
for (int i=0; i<max; i++) {
if (data[i+0] == iconst_1 && data[i+1] == pop &&
data[i+2] == iconst_1 && data[i+3] == pop) {
boolean match = true;
for (int x=4; x<pattern.length; x++) {
if (data[i+x] != pattern[x]) {
match = false;
break;
}
}
if (match) {
throw new RuntimeException("method of unverifiable class should have been " +
"removed from the archive " + archive +
" , but was found at offset " + i);
}
}
}
System.out.println("Not found: method from unverifiable class has been removed");
}
}

View File

@ -0,0 +1,72 @@
/*
* Copyright (c) 2015, 2017, 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
* @summary a simple test for loading a class using the ext class loader in AppCDS
* AppCDS does not support uncompressed oops
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* jdk.internal.jvmstat/sun.jvmstat.monitor
* @compile test-classes/HelloExt.java
* @build sun.hotspot.WhiteBox
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* @run main HelloExtTest
*/
import jdk.test.lib.process.OutputAnalyzer;
public class HelloExtTest {
public static void main(String[] args) throws Exception {
JarBuilder.build("helloExt", "HelloExt");
String appJar = TestCommon.getTestJar("helloExt.jar");
JarBuilder.build(true, "WhiteBox", "sun/hotspot/WhiteBox");
String whiteBoxJar = TestCommon.getTestJar("WhiteBox.jar");
String bootClassPath = "-Xbootclasspath/a:" + whiteBoxJar;
TestCommon.dump(appJar,
TestCommon.list("org/omg/CORBA/ORB", "[Ljava/lang/Comparable;"),
bootClassPath, "-verbose:class", "--add-modules", "java.corba");
OutputAnalyzer output = TestCommon.execCommon("-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI",
"-cp", appJar, bootClassPath, "-verbose:class", "--add-modules", "java.corba", "HelloExt");
String prefix = ".class.load. ";
String class_pattern = ".*LambdaForm[$]MH[/][0123456789].*";
String suffix = ".*source: shared objects file.*";
String pattern = prefix + class_pattern + suffix;
output.shouldNotMatch(pattern);
output = TestCommon.execCommon("-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI",
"-cp", appJar, bootClassPath, "-verbose:class",
"-XX:+PrintSharedArchiveAndExit", "-XX:+PrintSharedDictionary",
"--add-modules", "java.corba", "HelloExt");
output.shouldNotMatch(class_pattern);
}
}

View File

@ -0,0 +1,44 @@
/*
* Copyright (c) 2015, 2017, 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
* @summary Hello World test for AppCDS
* AppCDS does not support uncompressed oops
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @compile test-classes/Hello.java
* @run main HelloTest
*/
public class HelloTest {
public static void main(String[] args) throws Exception {
TestCommon.test(JarBuilder.getOrCreateHelloJar(),
TestCommon.list("Hello"), "Hello");
}
}

View File

@ -0,0 +1,63 @@
/*
* Copyright (c) 2014, 2017, 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
* @summary Test the -XX:+IgnoreEmptyClassPaths flag
* AppCDS does not support uncompressed oops
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @compile test-classes/Hello.java
* @compile test-classes/HelloMore.java
* @run main IgnoreEmptyClassPaths
*/
import java.io.File;
import jdk.test.lib.process.OutputAnalyzer;
public class IgnoreEmptyClassPaths {
public static void main(String[] args) throws Exception {
String jar1 = JarBuilder.getOrCreateHelloJar();
String jar2 = JarBuilder.build("IgnoreEmptyClassPaths_more", "HelloMore");
String sep = File.pathSeparator;
String cp_dump = jar1 + sep + jar2 + sep;
String cp_exec = sep + jar1 + sep + sep + jar2 + sep;
TestCommon.testDump(cp_dump, TestCommon.list("Hello", "HelloMore"),
"-XX:+TraceClassPaths", "-XX:+IgnoreEmptyClassPaths");
OutputAnalyzer output = TestCommon.execCommon(
"-verbose:class",
"-cp", cp_exec,
"-XX:+IgnoreEmptyClassPaths", // should affect classpath even if placed after the "-cp" argument
"-XX:+TraceClassPaths",
"HelloMore");
TestCommon.checkExec(output);
}
}

View File

@ -0,0 +1,235 @@
/*
* Copyright (c) 2015, 2017, 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.
*
*/
/*
* @summary Simple jar builder
* Input: jarName className1 className2 ...
* do not specify extensions, just the names
* E.g. prot_domain ProtDomainA ProtDomainB
* Output: A jar containing compiled classes, placed in a test classes folder
* @library /open/test/lib
*/
import jdk.test.lib.JDKToolFinder;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
import java.io.File;
import java.util.ArrayList;
import sun.tools.jar.Main;
public class JarBuilder {
// to turn DEBUG on via command line: -DJarBuilder.DEBUG=[true, TRUE]
private static final boolean DEBUG = Boolean.parseBoolean(System.getProperty("JarBuilder.DEBUG", "false"));
private static final String classDir = System.getProperty("test.classes");
public static String getJarFilePath(String jarName) {
return classDir + File.separator + jarName + ".jar";
}
// jar all files under dir, with manifest file man, with an optional versionArgs
// for generating a multi-release jar.
// The jar command is as follows:
// jar cmf \
// <path to output jar> <path to the manifest file>\
// -C <path to the base classes> .\
// --release 9 -C <path to the versioned classes> .
// the last line begins with "--release" corresponds to the optional versionArgs.
public static void build(String jarName, File dir, String man, String ...versionArgs)
throws Exception {
ArrayList<String> args = new ArrayList<String>();
if (man != null) {
args.add("cfm");
} else {
args.add("cf");
}
args.add(classDir + File.separator + jarName + ".jar");
if (man != null) {
args.add(man);
}
args.add("-C");
args.add(dir.getAbsolutePath());
args.add(".");
for (String verArg : versionArgs) {
args.add(verArg);
}
createJar(args);
}
public static String build(String jarName, String ...classNames)
throws Exception {
return createSimpleJar(classDir, getJarFilePath(jarName), classNames);
}
public static String build(boolean classesInWorkDir, String jarName, String ...classNames)
throws Exception {
if (classesInWorkDir) {
return createSimpleJar(".", getJarFilePath(jarName), classNames);
} else {
return build(jarName, classNames);
}
}
public static String buildWithManifest(String jarName, String manifest,
String jarClassesDir, String ...classNames) throws Exception {
String jarPath = getJarFilePath(jarName);
ArrayList<String> args = new ArrayList<String>();
args.add("cvfm");
args.add(jarPath);
args.add(System.getProperty("test.src") + File.separator + "test-classes"
+ File.separator + manifest);
addClassArgs(args, jarClassesDir, classNames);
createJar(args);
return jarPath;
}
// Execute: jar uvf $jarFile -C $dir .
static void update(String jarFile, String dir) throws Exception {
String jarExe = JDKToolFinder.getJDKTool("jar");
ArrayList<String> args = new ArrayList<>();
args.add(jarExe);
args.add("uvf");
args.add(jarFile);
args.add("-C");
args.add(dir);
args.add(".");
executeProcess(args.toArray(new String[1]));
}
private static String createSimpleJar(String jarclassDir, String jarName,
String[] classNames) throws Exception {
ArrayList<String> args = new ArrayList<String>();
args.add("cf");
args.add(jarName);
addClassArgs(args, jarclassDir, classNames);
createJar(args);
return jarName;
}
private static void addClassArgs(ArrayList<String> args, String jarclassDir,
String[] classNames) {
for (String name : classNames) {
args.add("-C");
args.add(jarclassDir);
args.add(name + ".class");
}
}
private static void createJar(ArrayList<String> args) {
if (DEBUG) printIterable("createJar args: ", args);
Main jarTool = new Main(System.out, System.err, "jar");
if (!jarTool.run(args.toArray(new String[1]))) {
throw new RuntimeException("jar operation failed");
}
}
// Many AppCDS tests use the same simple "Hello.jar" which contains
// simple Hello.class and does not specify additional attributes.
// For this common use case, use this method to get the jar path.
// The method will check if the jar already exists
// (created by another test or test run), and will create the jar
// if it does not exist
public static String getOrCreateHelloJar() throws Exception {
String jarPath = getJarFilePath("hello");
File jarFile = new File(jarPath);
if (jarFile.exists()) {
return jarPath;
} else {
return build("hello", "Hello");
}
}
public static void compile(String dstPath, String source, String... extraArgs) throws Exception {
ArrayList<String> args = new ArrayList<String>();
args.add(JDKToolFinder.getCompileJDKTool("javac"));
args.add("-d");
args.add(dstPath);
if (extraArgs != null) {
for (String s : extraArgs) {
args.add(s);
}
}
args.add(source);
if (DEBUG) printIterable("compile args: ", args);
ProcessBuilder pb = new ProcessBuilder(args);
OutputAnalyzer output = new OutputAnalyzer(pb.start());
output.shouldHaveExitValue(0);
}
public static void signJar() throws Exception {
String keyTool = JDKToolFinder.getJDKTool("keytool");
String jarSigner = JDKToolFinder.getJDKTool("jarsigner");
String classDir = System.getProperty("test.classes");
String FS = File.separator;
executeProcess(keyTool,
"-genkey", "-keystore", "./keystore", "-alias", "mykey",
"-storepass", "abc123", "-keypass", "abc123",
"-dname", "CN=jvmtest")
.shouldHaveExitValue(0);
executeProcess(jarSigner,
"-keystore", "./keystore", "-storepass", "abc123", "-keypass",
"abc123", "-signedjar", classDir + FS + "signed_hello.jar",
classDir + FS + "hello.jar", "mykey")
.shouldHaveExitValue(0);
}
private static OutputAnalyzer executeProcess(String... cmds)
throws Exception {
JarBuilder.printArray("executeProcess: ", cmds);
return ProcessTools.executeProcess(new ProcessBuilder(cmds));
}
// diagnostic
public static void printIterable(String msg, Iterable<String> l) {
StringBuilder sum = new StringBuilder();
for (String s : l) {
sum.append(s).append(' ');
}
System.out.println(msg + sum.toString());
}
public static void printArray(String msg, String[] l) {
StringBuilder sum = new StringBuilder();
for (String s : l) {
sum.append(s).append(' ');
}
System.out.println(msg + sum.toString());
}
}

View File

@ -0,0 +1,107 @@
/*
* Copyright (c) 2014, 2017, 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
* @summary JvmtiEnv::AddToBootstrapClassLoaderSearch and JvmtiEnv::AddToSystemClassLoaderSearch should disable AppCDS
* AppCDS does not support uncompressed oops
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @bug 8060592
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @build sun.hotspot.WhiteBox
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* @compile test-classes/Hello.java
* @compile test-classes/JvmtiApp.java
* @run main JvmtiAddPath
*/
import java.io.File;
import jdk.test.lib.process.OutputAnalyzer;
import sun.hotspot.WhiteBox;
public class JvmtiAddPath {
static String use_whitebox_jar;
static String[] no_extra_matches = {};
static String[] check_appcds_enabled = {
"[class,load] ExtraClass source: shared object"
};
static String[] check_appcds_disabled = {
"[class,load] ExtraClass source: file:"
};
static void run(String cp, String... args) throws Exception {
run(no_extra_matches, cp, args);
}
static void run(String[] extra_matches, String cp, String... args) throws Exception {
String[] opts = {"-cp", cp, "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", use_whitebox_jar};
opts = TestCommon.concat(opts, args);
OutputAnalyzer output = TestCommon.execCommon(opts);
TestCommon.checkExec(output, extra_matches);
}
public static void main(String[] args) throws Exception {
JarBuilder.build("jvmti_addboot", "Hello");
JarBuilder.build("jvmti_addapp", "Hello");
JarBuilder.build("jvmti_app", "JvmtiApp", "ExtraClass");
JarBuilder.build(true, "WhiteBox", "sun/hotspot/WhiteBox");
// In all the test cases below, appJar does not contain Hello.class. Instead, we
// append JAR file(s) that contain Hello.class to the boot classpath, the app
// classpath, or both, and verify that Hello.class is loaded by the expected ClassLoader.
String appJar = TestCommon.getTestJar("jvmti_app.jar"); // contains JvmtiApp.class
String addappJar = TestCommon.getTestJar("jvmti_addapp.jar"); // contains Hello.class
String addbootJar = TestCommon.getTestJar("jvmti_addboot.jar"); // contains Hello.class
String twoAppJars = appJar + File.pathSeparator + addappJar;
String wbJar = TestCommon.getTestJar("WhiteBox.jar");
use_whitebox_jar = "-Xbootclasspath/a:" + wbJar;
TestCommon.testDump(appJar, TestCommon.list("JvmtiApp", "ExtraClass"), use_whitebox_jar);
System.out.println("Test case 1: not adding any paths - Hello.class should not be found");
run(check_appcds_enabled, appJar, "-Xlog:class+load", "JvmtiApp", "noadd"); // appcds should be enabled
System.out.println("Test case 2: add to boot classpath only - should find Hello.class in boot loader");
run(check_appcds_disabled, appJar, "-Xlog:class+load", "JvmtiApp", "bootonly", addbootJar); // appcds should be disabled
System.out.println("Test case 3: add to app classpath only - should find Hello.class in app loader");
run(appJar, "JvmtiApp", "apponly", addappJar);
System.out.println("Test case 4: add to boot and app paths - should find Hello.class in boot loader");
run(appJar, "JvmtiApp", "appandboot", addbootJar, addappJar);
System.out.println("Test case 5: add to app using -cp, but add to boot using JVMTI - should find Hello.class in boot loader");
run(twoAppJars, "JvmtiApp", "bootonly", addappJar);
System.out.println("Test case 6: add to app using AppCDS, but add to boot using JVMTI - should find Hello.class in boot loader");
TestCommon.testDump(twoAppJars, TestCommon.list("JvmtiApp", "ExtraClass", "Hello"), use_whitebox_jar);
run(twoAppJars, "JvmtiApp", "bootonly", addappJar);
System.out.println("Test case 7: add to app using AppCDS, no JVMTI calls - should find Hello.class in app loader");
run(twoAppJars, "JvmtiApp", "noadd-appcds");
}
}

View File

@ -0,0 +1,81 @@
/*
* Copyright (c) 2015, 2017, 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
* @summary Try different combination of mismatched UseAppCDS between dump time and run time.
* (Note: AppCDS does not support uncompressed oops.)
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @compile test-classes/CheckIfShared.java
* @build sun.hotspot.WhiteBox
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* @run main MismatchedUseAppCDS
*/
import jdk.test.lib.process.OutputAnalyzer;
public class MismatchedUseAppCDS {
public static void main(String[] args) throws Exception {
String wbJar = JarBuilder.build(true, "WhiteBox", "sun/hotspot/WhiteBox");
String use_whitebox_jar = "-Xbootclasspath/a:" + wbJar;
String appJar = JarBuilder.build("MismatchedUseAppCDS", "CheckIfShared");
OutputAnalyzer output;
// (1): dump with -XX:+UseAppCDS, but run with -XX:-UseAppCDS
TestCommon.testDump(appJar, TestCommon.list("CheckIfShared"),
// command-line arguments ...
"-XX:+UseAppCDS",
use_whitebox_jar);
output = TestCommon.exec(appJar,
// command-line arguments ...
use_whitebox_jar,
"-XX:-UseAppCDS",
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+WhiteBoxAPI",
"CheckIfShared", "false");
TestCommon.checkExec(output);
// (2): dump with -XX:-UseAppCDS, but run with -XX:+UseAppCDS
TestCommon.testDump(appJar, TestCommon.list("CheckIfShared"),
// command-line arguments ...
"-XX:-UseAppCDS",
use_whitebox_jar);
output = TestCommon.exec(appJar,
// command-line arguments ...
use_whitebox_jar,
"-XX:+UseAppCDS",
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+WhiteBoxAPI",
"CheckIfShared", "false");
TestCommon.checkExec(output);
}
}

View File

@ -0,0 +1,52 @@
/*
* Copyright (c) 2014, 2017, 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
* @summary When super class is missing during dumping, no crash should happen.
* AppCDS does not support uncompressed oops
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @compile test-classes/MissingSuper.java
* @run main MissingSuperTest
*/
public class MissingSuperTest {
public static void main(String[] args) throws Exception {
// The classes "MissingSuperSup" and "MissingSuperIntf" are intentionally not
// included into the jar to provoke the test condition
JarBuilder.build("missing_super", "MissingSuper",
"MissingSuperSub", "MissingSuperImpl");
String appJar = TestCommon.getTestJar("missing_super.jar");
TestCommon.test(appJar, TestCommon.list("MissingSuper",
"MissingSuperSub",
"MissingSuperImpl"),
"MissingSuper");
}
}

View File

@ -0,0 +1,144 @@
/*
* Copyright (c) 2015, 2017, 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
* @summary Run multiple processes with the same archive, ensure they share
* AppCDS does not support uncompressed oops
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @build sun.hotspot.WhiteBox
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* @compile test-classes/MultiProcClass.java
* @run main MultiProcessSharing
*/
import java.io.File;
import jdk.test.lib.Asserts;
import jdk.test.lib.Platform;
import jdk.test.lib.process.OutputAnalyzer;
import sun.hotspot.WhiteBox;
public class MultiProcessSharing {
static String useWbJar;
static String sharedClass1Jar;
static boolean checkPmap = false;
public static void main(String[] args) throws Exception {
String wbJar = JarBuilder.build(true, "WhiteBox", "sun/hotspot/WhiteBox");
useWbJar = "-Xbootclasspath/a:" + wbJar;
sharedClass1Jar = JarBuilder.build("shared_class1", "MultiProcClass");
// create an archive
OutputAnalyzer out = TestCommon.dump(sharedClass1Jar,
TestCommon.list("MultiProcClass"), useWbJar);
TestCommon.checkDump(out);
// determine whether OK to use pmap for extra test verification
long myPid = ProcessHandle.current().pid();
checkPmap = (Platform.isLinux() && (MultiProcClass.runPmap(myPid, false) == 0));
System.out.println("MultiProcessSharing: checkPmap is " + checkPmap);
// use an archive in several processes concurrently
int numProcesses = 3;
Thread[] threads = new Thread[numProcesses];
ProcessHandler[] processHandlers = new ProcessHandler[numProcesses];
for (int i = 0; i < numProcesses; i++) {
processHandlers[i] = new ProcessHandler(i);
threads[i] = new Thread(processHandlers[i]);
}
for (Thread t : threads) {
t.start();
}
for (Thread t : threads) {
try {
t.join();
} catch (InterruptedException ie) {
throw ie;
}
}
// check results
for (ProcessHandler ph : processHandlers) {
TestCommon.checkExec(ph.out);
if (checkPmap && !TestCommon.isUnableToMap(ph.out)) {
checkPmapOutput(ph.out.getOutput());
}
}
}
static class ProcessHandler implements Runnable {
int processNumber;
OutputAnalyzer out;
ProcessHandler(int processNumber) {
this.processNumber = processNumber;
}
@Override
public void run() {
try {
out = TestCommon.exec(sharedClass1Jar,
"-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", useWbJar,
"MultiProcClass", "" + processNumber, "" + checkPmap);
} catch (Exception e) {
throw new RuntimeException("Error occurred when using archive, exec()" + e);
}
}
}
private static void checkPmapOutput(String stdio) {
System.out.println("Checking pmap output ...");
String[] lines = stdio.split("\n");
boolean foundJsa = false;
boolean foundReadOnlyJsaSection = false;
for (String line : lines) {
if (line.contains(TestCommon.getCurrentArchiveName()))
System.out.println(line);
foundJsa = true;
if (line.contains("r--")) {
foundReadOnlyJsaSection = true;
}
// On certain ARM platforms system maps r/o memory mapped files
// as r/x; see JDK-8145694 for details
if ( (Platform.isARM() || Platform.isAArch64()) && line.contains("r-x") ) {
foundReadOnlyJsaSection = true;
}
}
Asserts.assertTrue(foundJsa && foundReadOnlyJsaSection);
}
}

View File

@ -0,0 +1,238 @@
/*
* Copyright (c) 2016, 2017, 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 MultiReleaseJars
* @bug 8170105
* @summary Test multi-release jar with AppCDS.
* AppCDS does not support uncompressed oops
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @library /test/lib
* @modules java.base/jdk.internal.misc
* jdk.jartool/sun.tools.jar
* @run main/othervm MultiReleaseJars
*/
import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.io.IOException;
import jdk.test.lib.process.OutputAnalyzer;
public class MultiReleaseJars {
static final int MAJOR_VERSION = Runtime.version().major();
static final String MAJOR_VERSION_STRING = String.valueOf(Runtime.version().major());
static String[] getMain() {
String[] sts = {
"package version;",
"public class Main {",
" public static void main(String[] args) {",
" Version version = new Version();",
" System.out.println(\"I am running on version \" + version.getVersion());",
" }",
"}"
};
return sts;
}
static String[] getVersion(int version) {
String[] sts = {
"package version;",
"public class Version {",
" public int getVersion(){ return " + version + "; }",
"}"
};
return sts;
}
static void writeFile(File file, String... contents) throws Exception {
if (contents == null) {
throw new java.lang.RuntimeException("No input for writing to file" + file);
}
FileOutputStream fos = new FileOutputStream(file);
PrintStream ps = new PrintStream(fos);
for (String str : contents) {
ps.println(str);
}
ps.close();
fos.close();
}
/* version.jar entries and files:
* META-INF/
* META-INF/MANIFEST.MF
* version/
* version/Main.class
* version/Version.class
* META-INF/versions/
* META-INF/versions/<major-version>/
* META-INF/versions/<major-version>/version/
* META-INF/versions/<major-version>/version/Version.class
*/
static void createClassFilesAndJar() throws Exception {
String tempDir = System.getProperty("test.classes");
File baseDir = new File(tempDir + File.separator + "base");
File vDir = new File(tempDir + File.separator + MAJOR_VERSION_STRING);
baseDir.mkdirs();
vDir.mkdirs();
File fileMain = TestCommon.getOutputSourceFile("Main.java");
writeFile(fileMain, getMain());
File fileVersion = TestCommon.getOutputSourceFile("Version.java");
writeFile(fileVersion, getVersion(7));
JarBuilder.compile(baseDir.getAbsolutePath(), fileVersion.getAbsolutePath(), "--release", "7");
JarBuilder.compile(baseDir.getAbsolutePath(), fileMain.getAbsolutePath(),
"-cp", baseDir.getAbsolutePath(), "--release", MAJOR_VERSION_STRING);
String[] meta = {
"Multi-Release: true",
"Main-Class: version.Main"
};
File metainf = new File(tempDir, "mf.txt");
writeFile(metainf, meta);
fileVersion = TestCommon.getOutputSourceFile("Version.java");
writeFile(fileVersion, getVersion(MAJOR_VERSION));
JarBuilder.compile(vDir.getAbsolutePath(), fileVersion.getAbsolutePath(), "--release", MAJOR_VERSION_STRING);
JarBuilder.build("version", baseDir, metainf.getAbsolutePath(),
"--release", MAJOR_VERSION_STRING, "-C", vDir.getAbsolutePath(), ".");
// the following jar file is for testing case-insensitive "Multi-Release"
// attibute name
String[] meta2 = {
"multi-Release: true",
"Main-Class: version.Main"
};
metainf = new File(tempDir, "mf2.txt");
writeFile(metainf, meta2);
JarBuilder.build("version2", baseDir, metainf.getAbsolutePath(),
"--release", MAJOR_VERSION_STRING, "-C", vDir.getAbsolutePath(), ".");
}
static void checkExecOutput(OutputAnalyzer output, String expectedOutput) throws Exception {
try {
TestCommon.checkExec(output, expectedOutput);
} catch (java.lang.RuntimeException re) {
String cause = re.getMessage();
if (!expectedOutput.equals(cause)) {
throw re;
}
}
}
public static void main(String... args) throws Exception {
// create version.jar which contains Main.class and Version.class.
// Version.class has two versions: 8 and the current version.
createClassFilesAndJar();
String mainClass = "version.Main";
String loadInfo = "[class,load] version.Version source: shared objects file";
String appClasses[] = {"version/Main", "version/Version"};
String appJar = TestCommon.getTestJar("version.jar");
String appJar2 = TestCommon.getTestJar("version2.jar");
String verboseMode = "-verbose:class";
String enableMultiRelease = "-Djdk.util.jar.enableMultiRelease=true";
String jarVersion = null;
String expectedOutput = null;
// 1. default to highest version
// if META-INF/versions exists, no other commandline options like -Djdk.util.jar.version and
// -Djdk.util.jar.enableMultiRelease passed to vm
OutputAnalyzer output = TestCommon.dump(appJar, appClasses);
output.shouldContain("Loading classes to share: done.");
output.shouldHaveExitValue(0);
output = TestCommon.exec(appJar, verboseMode, mainClass);
checkExecOutput(output, "I am running on version " + MAJOR_VERSION_STRING);
// 2. Test versions 7 and the current major version.
// -Djdk.util.jar.enableMultiRelease=true (or force), default is true.
// a) -Djdk.util.jar.version=7 does not exist in jar.
// It will fallback to the root version which is also 7 in this test.
// b) -Djdk.util.jar.version=MAJOR_VERSION exists in the jar.
for (int i : new int[] {7, MAJOR_VERSION}) {
jarVersion = "-Djdk.util.jar.version=" + i;
expectedOutput = "I am running on version " + i;
output = TestCommon.dump(appJar, appClasses, enableMultiRelease, jarVersion);
output.shouldContain("Loading classes to share: done.");
output.shouldHaveExitValue(0);
output = TestCommon.exec(appJar, verboseMode, mainClass);
checkExecOutput(output, expectedOutput);
}
// 3. For unsupported version, 5 and current major version + 1, the multiversion
// will be turned off, so it will use the default (root) version.
for (int i : new int[] {5, MAJOR_VERSION + 1}) {
jarVersion = "-Djdk.util.jar.version=" + i;
output = TestCommon.dump(appJar, appClasses, enableMultiRelease, jarVersion);
output.shouldHaveExitValue(0);
// With the fix for 8172218, multi-release jar is being handled in
// jdk corelib which doesn't emit the following warning message.
//output.shouldContain("JDK" + i + " is not supported in multiple version jars");
output = TestCommon.exec(appJar, verboseMode, mainClass);
if (i == 5)
checkExecOutput(output, "I am running on version 7");
else
checkExecOutput(output, "I am running on version " + MAJOR_VERSION_STRING);
}
// 4. If explicitly disabled from command line for multiversion jar, it will use default
// version at root regardless multiversion versions exists.
// -Djdk.util.jar.enableMultiRelease=false (not 'true' or 'force')
for (int i = 6; i < MAJOR_VERSION + 1; i++) {
jarVersion = "-Djdk.util.jar.version=" + i;
output = TestCommon.dump(appJar, appClasses, "-Djdk.util.jar.enableMultiRelease=false", jarVersion);
output.shouldHaveExitValue(0);
output = TestCommon.exec(appJar, verboseMode, mainClass);
expectedOutput = "I am running on version 7";
checkExecOutput(output, expectedOutput);
}
// 5. Sanity test with -Xbootclasspath/a
// AppCDS behaves the same as the non-AppCDS case. A multi-release
// jar file in the -Xbootclasspath/a will be ignored.
output = TestCommon.dump(appJar, appClasses, "-Xbootclasspath/a:" + appJar, enableMultiRelease, jarVersion);
output.shouldContain("Loading classes to share: done.");
output.shouldHaveExitValue(0);
output = TestCommon.exec(appJar, "-Xbootclasspath/a:" + appJar, verboseMode, mainClass);
checkExecOutput(output, "I am running on version 7");
// 6. Sanity test case-insensitive "Multi-Release" attribute name
output = TestCommon.dump(appJar2, appClasses);
output.shouldContain("Loading classes to share: done.");
output.shouldHaveExitValue(0);
output = TestCommon.exec(appJar2, verboseMode, mainClass);
checkExecOutput(output, "I am running on version " + MAJOR_VERSION_STRING);
}
}

View File

@ -0,0 +1,167 @@
/*
* Copyright (c) 2014, 2017, 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
* @summary classes with major version < JDK_1.5 (48) should not be included in CDS
* AppCDS does not support uncompressed oops
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @library /test/lib
* @modules java.base/jdk.internal.org.objectweb.asm
* java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @compile test-classes/Hello.java
* @run build TestCommon JarBuilder
* @run main OldClassTest
*/
import java.io.File;
import java.io.FileOutputStream;
import jdk.test.lib.process.OutputAnalyzer;
import java.nio.file.Files;
import java.util.*;
import jdk.internal.org.objectweb.asm.*;
public class OldClassTest implements Opcodes {
public static void main(String[] args) throws Exception {
File jarSrcFile = new File(JarBuilder.getOrCreateHelloJar());
File dir = new File(System.getProperty("test.classes", "."));
File jarFile = new File(dir, "OldClassTest_old.jar");
String jar = jarFile.getPath();
if (!jarFile.exists() || jarFile.lastModified() < jarSrcFile.lastModified()) {
createTestJarFile(jarSrcFile, jarFile);
} else {
System.out.println("Already up-to-date: " + jarFile);
}
String appClasses[] = TestCommon.list("Hello");
// CASE 1: pre-JDK 1.5 compiled classes should be excluded from the dump
OutputAnalyzer output = TestCommon.dump(jar, appClasses);
TestCommon.checkExecReturn(output, 0, true, "Pre JDK 1.5 class not supported by CDS");
output = TestCommon.execCommon(
"-cp", jar,
"-verbose:class",
"Hello");
TestCommon.checkExecReturn(output, 0, true, "Hello Unicode world (Old)");
// CASE 2: if we exlcude old version of this class, we should not pick up
// the newer version of this class in a subsequent classpath element.
String classpath = jar + File.pathSeparator + jarSrcFile.getPath();
output = TestCommon.dump(classpath, appClasses);
TestCommon.checkExecReturn(output, 0, true, "Pre JDK 1.5 class not supported by CDS");
output = TestCommon.execCommon(
"-cp", classpath,
"-verbose:class",
"Hello");
TestCommon.checkExecReturn(output, 0, true, "Hello Unicode world (Old)");
}
static void createTestJarFile(File jarSrcFile, File jarFile) throws Exception {
jarFile.delete();
Files.copy(jarSrcFile.toPath(), jarFile.toPath());
File dir = new File(System.getProperty("test.classes", "."));
File outdir = new File(dir, "old_class_test_classes");
outdir.delete();
outdir.mkdir();
writeClassFile(new File(outdir, "Hello.class"), makeOldHello());
JarBuilder.update(jarFile.getPath(), outdir.getPath());
}
static void writeClassFile(File file, byte bytecodes[]) throws Exception {
try (FileOutputStream fos = new FileOutputStream(file)) {
fos.write(bytecodes);
}
}
/* makeOldHello() was obtained using JDK8. We use a method name > 128 that would
trigger a call to java.lang.Character.isJavaIdentifierStart() during class
file parsing.
cat > Hello.java <<EOF
public class Hello {
public static void main(String args[]) {
System.out.println(\u1234());
}
static String \u1234() {
return "Hello Unicode world (Old)";
}
}
EOF
javac Hello.java
java jdk.internal.org.objectweb.asm.util.ASMifier Hello.class
*/
static byte[] makeOldHello() throws Exception {
ClassWriter cw = new ClassWriter(0);
FieldVisitor fv;
MethodVisitor mv;
AnnotationVisitor av0;
//WAS cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER, "Hello", null, "java/lang/Object", null);
cw.visit(V1_4, ACC_PUBLIC + ACC_SUPER, "Hello", null, "java/lang/Object", null);
{
mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null);
mv.visitCode();
mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
mv.visitMethodInsn(INVOKESTATIC, "Hello", "\u1234", "()Ljava/lang/String;", false);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(2, 1);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_STATIC, "\u1234", "()Ljava/lang/String;", null, null);
mv.visitCode();
mv.visitLdcInsn("Hello Unicode world (Old)");
mv.visitInsn(ARETURN);
mv.visitMaxs(1, 0);
mv.visitEnd();
}
cw.visitEnd();
return cw.toByteArray();
}
}

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2014, 2017, 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
* @summary AppCDS handling of package.
* AppCDS does not support uncompressed oops
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.management
* @compile test-classes/C1.java
* @compile test-classes/C2.java
* @compile test-classes/PackageSealingTest.java
* @run main PackageSealing
*/
import jdk.test.lib.process.OutputAnalyzer;
public class PackageSealing {
public static void main(String args[]) throws Exception {
String[] classList = {"sealed/pkg/C1", "pkg/C2", "PackageSealingTest"};
String appJar = ClassFileInstaller.writeJar("pkg_seal.jar",
ClassFileInstaller.Manifest.fromSourceFile("test-classes/package_seal.mf"),
"PackageSealingTest", "sealed/pkg/C1", "pkg/C2");
// test shared package from -cp path
TestCommon.testDump(appJar, TestCommon.list(classList));
OutputAnalyzer output;
output = TestCommon.exec(appJar, "PackageSealingTest");
TestCommon.checkExec(output, "OK");
// test shared package from -Xbootclasspath/a
TestCommon.dump(appJar, TestCommon.list(classList),
"-Xbootclasspath/a:" + appJar);
output = TestCommon.exec(appJar, "-Xbootclasspath/a:" + appJar, "PackageSealingTest");
TestCommon.checkExec(output, "OK");
}
}

View File

@ -0,0 +1,64 @@
/*
* Copyright (c) 2014, 2017, 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
* @summary Load app classes from CDS archive in parallel threads. Similar to ParallelLoad.java, but each class in its own JAR
* AppCDS does not support uncompressed oops
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @compile test-classes/ParallelLoad.java
* @compile test-classes/ParallelClasses.java
* @run main ParallelLoad2
*/
import java.io.File;
public class ParallelLoad2 {
public static int MAX_CLASSES = 40;
public static void main(String[] args) throws Exception {
JarBuilder.build("parallel_load2", "ParallelLoad", "ParallelLoadThread", "ParallelLoadWatchdog");
for (int i=0; i<MAX_CLASSES; i++) {
JarBuilder.build("parallel_load2_" + i, "ParallelClass" + i);
}
String cp = TestCommon.getTestJar("parallel_load2.jar");
for (int i=0; i<MAX_CLASSES; i++) {
cp += File.pathSeparator + TestCommon.getTestJar("parallel_load2_" + i + ".jar");
}
String[] class_list = new String[MAX_CLASSES + 2];
for (int i=0; i<MAX_CLASSES; i++) {
class_list[i] = "ParallelClass" + i;
}
class_list[class_list.length - 1] = "ParallelLoad";
class_list[class_list.length - 2] = "ParallelLoadThread";
TestCommon.test(cp, class_list,
"ParallelLoad");
}
}

View File

@ -0,0 +1,64 @@
/*
* Copyright (c) 2014, 2017, 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
* @summary Load app classes from CDS archive in parallel threads
* AppCDS does not support uncompressed oops
* @library /test/lib
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @compile test-classes/ParallelLoad.java
* @compile test-classes/ParallelClasses.java
* @run main ParallelLoadTest
*/
public class ParallelLoadTest {
public static final int MAX_CLASSES = 40;
public static void main(String[] args) throws Exception {
JarBuilder.build("parallel_load", getClassList(true));
String appJar = TestCommon.getTestJar("parallel_load.jar");
TestCommon.test(appJar, getClassList(false), "ParallelLoad");
}
private static String[] getClassList(boolean includeWatchdog) {
int extra = includeWatchdog ? 3 : 2;
String[] classList = new String[MAX_CLASSES + extra];
int i;
for (i=0; i<MAX_CLASSES; i++) {
classList[i] = "ParallelClass" + i;
}
classList[i++] = "ParallelLoad";
classList[i++] = "ParallelLoadThread";
if (includeWatchdog)
classList[i++] = "ParallelLoadWatchdog";
return classList;
}
}

View File

@ -0,0 +1,148 @@
/*
* Copyright (c) 2014, 2017, 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
* @summary test the -XX:+PrintSharedArchiveAndExit flag
* AppCDS does not support uncompressed oops
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @compile test-classes/Hello.java
* @compile test-classes/HelloMore.java
* @run main/othervm/timeout=3600 PrintSharedArchiveAndExit
*/
import java.io.File;
import jdk.test.lib.process.OutputAnalyzer;
public class PrintSharedArchiveAndExit {
private static void check(OutputAnalyzer output, int ret, boolean checkContain, String... matches) throws Exception {
// Tests specific to this test
TestCommon.checkExecReturn(output, ret, checkContain, matches);
// In all test case, we should never print out the following due to
// PrintSharedArchiveAndExit. JVM should have been terminated
// before reaching these outputs.
TestCommon.checkExecReturn(output, ret, false,
"Usage:", // JVM help message
"java version", // JVM version
"Hello World"); // output from the Hello.class in hello.jar
}
private static void log(String msg) {
System.out.println(">---------------------------------------------------------------------");
System.out.println(msg);
System.out.println("<---------------------------------------------------------------------");
}
public static void main(String[] args) throws Exception {
String appJar = JarBuilder.getOrCreateHelloJar();
String appJar2 = JarBuilder.build("PrintSharedArchiveAndExit-more", "HelloMore");
String cp = appJar + File.pathSeparator + appJar2;
String lastCheckMsg = "checking shared classpath entry: " + appJar2; // the last JAR to check
TestCommon.testDump(cp, TestCommon.list("Hello"));
OutputAnalyzer output;
log("Normal execution -- all the JAR paths should be checked");
output = TestCommon.execCommon(
"-cp", cp,
"-XX:+PrintSharedArchiveAndExit");
check(output, 0, true, lastCheckMsg);
output = TestCommon.execCommon(
"-cp", cp,
"-XX:+PrintSharedArchiveAndExit",
"-XX:+PrintSharedDictionary"); // Test PrintSharedDictionary as well.
check(output, 0, true, lastCheckMsg, "java.lang.Object");
log("Normal execution -- Make sure -version, help message and app main()\n" +
"class are not invoked. These are checked inside check().");
output = TestCommon.execCommon("-cp", cp, "-XX:+PrintSharedArchiveAndExit", "-version");
check(output, 0, true, lastCheckMsg);
output = TestCommon.execCommon("-cp", cp, "-XX:+PrintSharedArchiveAndExit", "-help");
check(output, 0, true, lastCheckMsg);
output = TestCommon.execCommon("-cp", cp, "-XX:+PrintSharedArchiveAndExit", "Hello");
check(output, 0, true, lastCheckMsg);
log("Execution with simple errors -- with 'simple' errors like missing or modified\n" +
"JAR files, the VM should try to continue to print the remaining information.\n" +
"Use an invalid Boot CP -- all the JAR paths should be checked");
output = TestCommon.execCommon(
"-cp", cp,
"-Xbootclasspath/a:foo.jar",
"-XX:+PrintSharedArchiveAndExit");
check(output, 1, true, lastCheckMsg, "[BOOT classpath mismatch, ");
log("Use an App CP shorter than the one at dump time -- all the JAR paths should be checked");
output = TestCommon.execCommon(
"-cp", ".",
"-XX:+PrintSharedArchiveAndExit");
check(output, 1, true, lastCheckMsg, "Run time APP classpath is shorter than the one at dump time: .");
log("Use an invalid App CP -- all the JAR paths should be checked");
String invalidCP = "non-existing-dir" + File.pathSeparator + cp;
output = TestCommon.execCommon(
"-cp", invalidCP,
"-XX:+PrintSharedArchiveAndExit");
check(output, 1, true, lastCheckMsg, "APP classpath mismatch, actual: -Djava.class.path=" + invalidCP);
log("Changed modification time of hello.jar -- all the JAR paths should be checked");
(new File(appJar)).setLastModified(System.currentTimeMillis() + 2000);
output = TestCommon.execCommon(
"-cp", cp,
"-XX:+PrintSharedArchiveAndExit");
check(output, 1, true, lastCheckMsg, "[Timestamp mismatch]");
log("Even if hello.jar is out of date, we should still be able to print the dictionary.");
output = TestCommon.execCommon(
"-cp", cp,
"-XX:+PrintSharedArchiveAndExit",
"-XX:+PrintSharedDictionary"); // Test PrintSharedDictionary as well.
check(output, 1, true, lastCheckMsg, "java.lang.Object");
log("Remove hello.jar -- all the JAR paths should be checked");
(new File(appJar)).delete();
output = TestCommon.execCommon(
"-cp", cp,
"-XX:+PrintSharedArchiveAndExit");
check(output, 1, true, lastCheckMsg, "[Required classpath entry does not exist: " + appJar + "]");
log("Execution with major errors -- with 'major' errors like the JSA file\n" +
"is missing, we should stop immediately to avoid crashing the JVM.");
output = TestCommon.execCommon(
"-cp", cp,
"-XX:+PrintSharedArchiveAndExit",
"-XX:SharedArchiveFile=./no-such-fileappcds.jsa");
check(output, 1, false, lastCheckMsg);
}
}

View File

@ -0,0 +1,101 @@
/*
* Copyright (c) 2014, 2017, 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
* @summary AppCDS handling of prohibited package.
* AppCDS does not support uncompressed oops
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @compile test-classes/ProhibitedHelper.java test-classes/Prohibited.jasm
* @run main ProhibitedPackage
*/
import jdk.test.lib.Platform;
import jdk.test.lib.process.OutputAnalyzer;
public class ProhibitedPackage {
public static void main(String[] args) throws Exception {
JarBuilder.build("prohibited_pkg", "java/lang/Prohibited", "ProhibitedHelper");
String appJar = TestCommon.getTestJar("prohibited_pkg.jar");
// AppCDS for custom loader is only supported on linux-x64 and
// Solaris 64-bit platforms.
if ((Platform.isLinux() || Platform.isSolaris()) &&
Platform.is64bit()) {
String classlist[] = new String[] {
"java/lang/Object id: 1",
"java/lang/Prohibited id: 2 super: 1 source: " + appJar
};
// Make sure a class in a prohibited package for a custom loader
// will be ignored during dumping.
TestCommon.dump(appJar,
classlist,
"-XX:+PrintSystemDictionaryAtExit")
.shouldContain("Dumping")
.shouldNotContain("java.lang.Prohibited")
.shouldHaveExitValue(0);
}
// Make sure a class in a prohibited package for a non-custom loader
// will be ignored during dumping.
TestCommon.dump(appJar,
TestCommon.list("java/lang/Prohibited", "ProhibitedHelper"),
"-XX:+PrintSystemDictionaryAtExit")
.shouldContain("Dumping")
.shouldNotContain("java.lang.Prohibited")
.shouldHaveExitValue(0);
// Try loading the class in a prohibited package with various -Xshare
// modes. The class shouldn't be loaded and appropriate exceptions
// are expected.
OutputAnalyzer output;
// -Xshare:on
output = TestCommon.execCommon(
"-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI",
"-cp", appJar, "-Xlog:class+load=info", "ProhibitedHelper");
TestCommon.checkExec(output, "Prohibited package name: java.lang");
// -Xshare:auto
output = TestCommon.execAuto(
"-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI",
"-cp", appJar, "-Xlog:class+load=info", "ProhibitedHelper");
TestCommon.checkExec(output, "Prohibited package name: java.lang");
// -Xshare:off
output = TestCommon.execOff(
"-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI",
"-cp", appJar, "-Xlog:class+load=info", "ProhibitedHelper");
output.shouldContain("Prohibited package name: java.lang");
}
}

View File

@ -0,0 +1,73 @@
/*
* Copyright (c) 2014, 2017, 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
* @summary AppCDS handling of protection domain.
* AppCDS does not support uncompressed oops
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @compile test-classes/ProtDomain.java
* @compile test-classes/ProtDomainB.java
* @compile test-classes/JimageClassProtDomain.java
* @run main ProtectionDomain
*/
import jdk.test.lib.process.OutputAnalyzer;
public class ProtectionDomain {
public static void main(String[] args) throws Exception {
JarBuilder.build("prot_domain", "ProtDomain", "ProtDomainB", "ProtDomainOther",
"ProtDomainBOther", "JimageClassProtDomain");
String appJar = TestCommon.getTestJar("prot_domain.jar");
TestCommon.testDump(appJar,
TestCommon.list("ProtDomain",
"ProtDomainBOther",
"java/util/Dictionary",
"sun/tools/javac/Main",
"jdk/nio/zipfs/ZipInfo",
"java/net/URL",
"sun/rmi/rmic/Main",
"com/sun/jndi/dns/DnsName"));
OutputAnalyzer output;
// First class is loaded from CDS, second class is loaded from JAR
output = TestCommon.exec(appJar, "-verbose:class", "ProtDomain");
TestCommon.checkExec(output, "Protection Domains match");
// First class is loaded from JAR, second class is loaded from CDS
output = TestCommon.exec(appJar, "-verbose:class", "ProtDomainB");
TestCommon.checkExec(output, "Protection Domains match");
// Test ProtectionDomain for application and extension module classes from the
// "modules" jimage
output = TestCommon.exec(appJar, "-verbose:class", "JimageClassProtDomain");
output.shouldNotContain("Failed: Protection Domains do not match");
}
}

View File

@ -0,0 +1,65 @@
/*
* Copyright (c) 2015, 2017, 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
* @summary Use ClassLoader.defineClass() to load a class with rewritten bytecode. Make sure
* the archived class with the same name is not loaded.
* AppCDS does not support uncompressed oops
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @compile test-classes/RewriteBytecodes.java test-classes/Util.java test-classes/Super.java test-classes/Child.java
* @build sun.hotspot.WhiteBox
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* @run main RewriteBytecodesTest
*/
import java.io.File;
import jdk.test.lib.process.OutputAnalyzer;
public class RewriteBytecodesTest {
public static void main(String[] args) throws Exception {
String wbJar = JarBuilder.build(true, "WhiteBox", "sun/hotspot/WhiteBox");
String use_whitebox_jar = "-Xbootclasspath/a:" + wbJar;
String appJar = JarBuilder.build("dynamic_define", "RewriteBytecodes", "Util", "Super", "Child");
String superClsFile = (new File(System.getProperty("test.classes", "."), "Super.class")).getPath();
TestCommon.dump(appJar, TestCommon.list("RewriteBytecodes", "Super", "Child"),
// command-line arguments ...
use_whitebox_jar);
OutputAnalyzer output = TestCommon.exec(appJar,
// command-line arguments ...
"--add-opens=java.base/java.lang=ALL-UNNAMED",
use_whitebox_jar,
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+WhiteBoxAPI",
"RewriteBytecodes", superClsFile);
TestCommon.checkExec(output);
}
}

View File

@ -0,0 +1,386 @@
/*
* Copyright (c) 2014, 2017, 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
* @summary SharedArchiveConsistency
* AppCDS does not support uncompressed oops
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
* jdk.jartool/sun.tools.jar
* jdk.internal.jvmstat/sun.jvmstat.monitor
* @build sun.hotspot.WhiteBox
* @compile test-classes/Hello.java
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI SharedArchiveConsistency
*/
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.Utils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
import java.nio.file.StandardOpenOption;
import static java.nio.file.StandardOpenOption.READ;
import static java.nio.file.StandardOpenOption.WRITE;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import sun.hotspot.WhiteBox;
public class SharedArchiveConsistency {
public static WhiteBox wb;
public static int offset_magic; // FileMapHeader::_magic
public static int sp_offset_crc; // FileMapHeader::space_info::_crc
public static int file_header_size = -1;// total size of header, variant, need calculation
public static int space_info_size; // size of space_info
public static int sp_offset; // offset of FileMapHeader::space_info
public static int sp_used_offset; // offset of space_info::_used
public static int size_t_size; // size of size_t
public static File jsa; // will be updated during test
public static File orgJsaFile; // kept the original file not touched.
public static String[] shared_region_name = {"MiscCode", "ReadWrite", "ReadOnly", "MiscData"};
public static int num_regions = shared_region_name.length;
public static String[] matchMessages = {
"Unable to use shared archive",
"An error has occurred while processing the shared archive file.",
"Checksum verification failed.",
"The shared archive file has been truncated."
};
public static void getFileOffsetInfo() throws Exception {
wb = WhiteBox.getWhiteBox();
offset_magic = wb.getOffsetForName("FileMapHeader::_magic");
sp_offset_crc = wb.getOffsetForName("space_info::_crc");
try {
int nonExistOffset = wb.getOffsetForName("FileMapHeader::_non_exist_offset");
System.exit(-1); // should fail
} catch (Exception e) {
// success
}
sp_offset = wb.getOffsetForName("FileMapHeader::_space[0]") - offset_magic;
sp_used_offset = wb.getOffsetForName("space_info::_used") - sp_offset_crc;
size_t_size = wb.getOffsetForName("size_t_size");
space_info_size = wb.getOffsetForName("space_info_size");
}
public static int getFileHeaderSize(FileChannel fc) throws Exception {
if (file_header_size != -1) {
return file_header_size;
}
// this is not real header size, it is struct size
file_header_size = wb.getOffsetForName("file_header_size");
int offset_path_misc_info = wb.getOffsetForName("FileMapHeader::_paths_misc_info_size") -
offset_magic;
int path_misc_info_size = (int)readInt(fc, offset_path_misc_info, size_t_size);
file_header_size += path_misc_info_size; //readInt(fc, offset_path_misc_info, size_t_size);
System.out.println("offset_path_misc_info = " + offset_path_misc_info);
System.out.println("path_misc_info_size = " + path_misc_info_size);
System.out.println("file_header_size = " + file_header_size);
file_header_size = (int)align_up_page(file_header_size);
System.out.println("file_header_size (aligned to page) = " + file_header_size);
return file_header_size;
}
public static long align_up_page(long l) throws Exception {
// wb is obtained in getFileOffsetInfo() which is called first in main() else we should call
// WhiteBox.getWhiteBox() here first.
int pageSize = wb.getVMPageSize();
return (l + pageSize -1) & (~ (pageSize - 1));
}
private static long getRandomBetween(long start, long end) throws Exception {
if (start > end) {
throw new IllegalArgumentException("start must be less than end");
}
Random aRandom = Utils.getRandomInstance();
int d = aRandom.nextInt((int)(end - start));
if (d < 1) {
d = 1;
}
return start + d;
}
public static long readInt(FileChannel fc, long offset, int nbytes) throws Exception {
ByteBuffer bb = ByteBuffer.allocate(nbytes);
bb.order(ByteOrder.nativeOrder());
fc.position(offset);
fc.read(bb);
return (nbytes > 4 ? bb.getLong(0) : bb.getInt(0));
}
public static void writeData(FileChannel fc, long offset, ByteBuffer bb) throws Exception {
fc.position(offset);
fc.write(bb);
fc.force(true);
}
public static FileChannel getFileChannel() throws Exception {
List<StandardOpenOption> arry = new ArrayList<StandardOpenOption>();
arry.add(READ);
arry.add(WRITE);
return FileChannel.open(jsa.toPath(), new HashSet<StandardOpenOption>(arry));
}
public static void modifyJsaContentRandomly() throws Exception {
FileChannel fc = getFileChannel();
// corrupt random area in the data areas (MiscCode, ReadWrite, ReadOnly, MiscData)
long[] used = new long[num_regions]; // record used bytes
long start0, start, end, off;
int used_offset, path_info_size;
int bufSize;
System.out.printf("%-12s%-12s%-12s%-12s%-12s\n", "Space Name", "Offset", "Used bytes", "Reg Start", "Random Offset");
start0 = getFileHeaderSize(fc);
for (int i = 0; i < num_regions; i++) {
used_offset = sp_offset + space_info_size * i + sp_used_offset;
// read 'used'
used[i] = readInt(fc, used_offset, size_t_size);
start = start0;
for (int j = 0; j < i; j++) {
start += align_up_page(used[j]);
}
end = start + used[i];
off = getRandomBetween(start, end);
System.out.printf("%-12s%-12d%-12d%-12d%-12d\n", shared_region_name[i], used_offset, used[i], start, off);
if (end - off < 1024) {
bufSize = (int)(end - off + 1);
} else {
bufSize = 1024;
}
ByteBuffer bbuf = ByteBuffer.wrap(new byte[bufSize]);
writeData(fc, off, bbuf);
}
if (fc.isOpen()) {
fc.close();
}
}
public static void modifyJsaContent() throws Exception {
FileChannel fc = getFileChannel();
byte[] buf = new byte[4096];
ByteBuffer bbuf = ByteBuffer.wrap(buf);
long total = 0L;
long used_offset = 0L;
long[] used = new long[num_regions];
System.out.printf("%-12s%-12s\n", "Space name", "Used bytes");
for (int i = 0; i < num_regions; i++) {
used_offset = sp_offset + space_info_size* i + sp_used_offset;
// read 'used'
used[i] = readInt(fc, used_offset, size_t_size);
System.out.printf("%-12s%-12d\n", shared_region_name[i], used[i]);
total += used[i];
}
System.out.printf("%-12s%-12d\n", "Total: ", total);
long corrupt_used_offset = getFileHeaderSize(fc);
System.out.println("Corrupt RO section, offset = " + corrupt_used_offset);
while (used_offset < used[0]) {
writeData(fc, corrupt_used_offset, bbuf);
bbuf.clear();
used_offset += 4096;
}
fc.force(true);
if (fc.isOpen()) {
fc.close();
}
}
public static void modifyJsaHeader() throws Exception {
FileChannel fc = getFileChannel();
// screw up header info
byte[] buf = new byte[getFileHeaderSize(fc)];
ByteBuffer bbuf = ByteBuffer.wrap(buf);
writeData(fc, 0L, bbuf);
if (fc.isOpen()) {
fc.close();
}
}
public static void copyFile(File from, File to) throws Exception {
if (to.exists()) {
if(!to.delete()) {
throw new IOException("Could not delete file " + to);
}
}
to.createNewFile();
setReadWritePermission(to);
Files.copy(from.toPath(), to.toPath(), REPLACE_EXISTING);
}
// Copy file with bytes deleted or inserted
// del -- true, deleted, false, inserted
public static void copyFile(File from, File to, boolean del) throws Exception {
FileChannel inputChannel = null;
FileChannel outputChannel = null;
try {
inputChannel = new FileInputStream(from).getChannel();
outputChannel = new FileOutputStream(to).getChannel();
long size = inputChannel.size();
int init_size = getFileHeaderSize(inputChannel);
outputChannel.transferFrom(inputChannel, 0, init_size);
int n = (int)getRandomBetween(0, 1024);
if (del) {
System.out.println("Delete " + n + " bytes at data start section");
inputChannel.position(init_size + n);
outputChannel.transferFrom(inputChannel, init_size, size - init_size - n);
} else {
System.out.println("Insert " + n + " bytes at data start section");
outputChannel.position(init_size);
outputChannel.write(ByteBuffer.wrap(new byte[n]));
outputChannel.transferFrom(inputChannel, init_size + n , size - init_size);
}
} finally {
inputChannel.close();
outputChannel.close();
}
}
public static void restoreJsaFile() throws Exception {
Files.copy(orgJsaFile.toPath(), jsa.toPath(), REPLACE_EXISTING);
}
public static void setReadWritePermission(File file) throws Exception {
if (!file.canRead()) {
if (!file.setReadable(true)) {
throw new IOException("Cannot modify file " + file + " as readable");
}
}
if (!file.canWrite()) {
if (!file.setWritable(true)) {
throw new IOException("Cannot modify file " + file + " as writable");
}
}
}
public static void testAndCheck(String[] execArgs) throws Exception {
OutputAnalyzer output = TestCommon.execCommon(execArgs);
String stdtxt = output.getOutput();
System.out.println("Note: this test may fail in very rare occasions due to CRC32 checksum collision");
for (String message : matchMessages) {
if (stdtxt.contains(message)) {
// match any to return
return;
}
}
TestCommon.checkExec(output);
}
// dump with hello.jsa, then
// read the jsa file
// 1) run normal
// 2) modify header
// 3) keep header correct but modify content
// 4) update both header and content, test
// 5) delete bytes in data begining
// 6) insert bytes in data begining
// 7) randomly corrupt data in four areas: RO, RW. MISC DATA, MISC CODE
public static void main(String... args) throws Exception {
// must call to get offset info first!!!
getFileOffsetInfo();
Path currentRelativePath = Paths.get("");
String currentDir = currentRelativePath.toAbsolutePath().toString();
System.out.println("Current relative path is: " + currentDir);
// get jar file
String jarFile = JarBuilder.getOrCreateHelloJar();
// dump (appcds.jsa created)
TestCommon.testDump(jarFile, null);
// test, should pass
System.out.println("1. Normal, should pass but may fail\n");
String[] execArgs = {"-cp", jarFile, "Hello"};
OutputAnalyzer output = TestCommon.execCommon(execArgs);
try {
TestCommon.checkExecReturn(output, 0, true, "Hello World");
} catch (Exception e) {
TestCommon.checkExecReturn(output, 1, true, matchMessages[0]);
}
// get current archive name
jsa = new File(TestCommon.getCurrentArchiveName());
if (!jsa.exists()) {
throw new IOException(jsa + " does not exist!");
}
setReadWritePermission(jsa);
// save as original untouched
orgJsaFile = new File(new File(currentDir), "appcds.jsa.bak");
copyFile(jsa, orgJsaFile);
// modify jsa header, test should fail
System.out.println("\n2. Corrupt header, should fail\n");
modifyJsaHeader();
output = TestCommon.execCommon(execArgs);
output.shouldContain("The shared archive file has the wrong version");
output.shouldNotContain("Checksum verification failed");
// modify content
System.out.println("\n3. Corrupt Content, should fail\n");
copyFile(orgJsaFile, jsa);
modifyJsaContent();
testAndCheck(execArgs);
// modify both header and content, test should fail
System.out.println("\n4. Corrupt Header and Content, should fail\n");
copyFile(orgJsaFile, jsa);
modifyJsaHeader();
modifyJsaContent(); // this will not be reached since failed on header change first
output = TestCommon.execCommon(execArgs);
output.shouldContain("The shared archive file has the wrong version");
output.shouldNotContain("Checksum verification failed");
// delete bytes in data sectoin
System.out.println("\n5. Delete bytes at begining of data section, should fail\n");
copyFile(orgJsaFile, jsa, true);
testAndCheck(execArgs);
// insert bytes in data sectoin forward
System.out.println("\n6. Insert bytes at begining of data section, should fail\n");
copyFile(orgJsaFile, jsa, false);
testAndCheck(execArgs);
System.out.println("\n7. modify Content in random areas, should fail\n");
copyFile(orgJsaFile, jsa);
modifyJsaContentRandomly();
testAndCheck(execArgs);
}
}

View File

@ -0,0 +1,83 @@
/*
* Copyright (c) 2014, 2017, 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
* @summary The diagnostic option, -XX:SharedArchiveFile can be unlocked using -XX:+UseAppCDS
* AppCDS does not support uncompressed oops
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @compile test-classes/Hello.java
* @run main SharedArchiveFile
*/
import jdk.test.lib.Platform;
import jdk.test.lib.cds.CDSTestUtils;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
import java.util.Properties;
public class SharedArchiveFile {
public static void main(String[] args) throws Exception {
boolean isProduct = !Platform.isDebugBuild();
String appJar = JarBuilder.getOrCreateHelloJar();
// 1) Using -XX:SharedArchiveFile without -XX:+UseAppCDS should fail
// on product binary without -XX:+UnlockDiagnosticVMOptions.
if (isProduct) {
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true,
"-XX:SharedArchiveFile=./SharedArchiveFile.jsa", "-Xshare:dump");
OutputAnalyzer out = CDSTestUtils.executeAndLog(pb, "dump");
out.shouldContain("Error: VM option 'SharedArchiveFile' is diagnostic and must be enabled via -XX:+UnlockDiagnosticVMOptions.");
}
// 2) Dumping with -XX:+UnlockDiagnosticVMOptions -XX:SharedArchiveFile
// should always succeed.
CDSTestUtils.createArchive("-XX:+UnlockDiagnosticVMOptions")
.shouldContain("Dumping");
// 3) Using -XX:SharedArchiveFile with -XX:+UseAppCDS should work
// on product binary by default.
OutputAnalyzer output3 = TestCommon.dump(appJar, TestCommon.list("Hello"));
output3.shouldContain("Dumping");
output3 = TestCommon.exec(appJar, "Hello");
TestCommon.checkExec(output3, "Hello World");
// 4) Using -XX:+UseAppCDS should not affect other diagnostic flags,
// such as LogEvents
OutputAnalyzer output4 = TestCommon.exec(appJar, "-XX:+LogEvents", "Hello");
if (isProduct) {
output4.shouldContain("Error: VM option 'LogEvents' is diagnostic and must be enabled via -XX:+UnlockDiagnosticVMOptions.");
} else {
TestCommon.checkExec(output4, "Hello World");
}
// 5) 8066921 - Extra -XX:+UseAppCDS
TestCommon.testDump(appJar, TestCommon.list("Hello"), "-XX:+UseAppCDS");
OutputAnalyzer output5 = TestCommon.exec(appJar, "-XX:+UseAppCDS", "Hello");
TestCommon.checkExec(output5);
}
}

View File

@ -0,0 +1,65 @@
/*
* Copyright (c) 2014, 2017, 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 SharedBaseAddress
* @summary Test variety of values for SharedBaseAddress, in AppCDS mode,
* making sure VM handles normal values as well as edge values
* w/o a crash.
* AppCDS does not support uncompressed oops
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @compile test-classes/Hello.java
* @run main/timeout=240 SharedBaseAddress
*/
import jdk.test.lib.process.OutputAnalyzer;
public class SharedBaseAddress {
// shared base address test table
private static final String[] testTable = {
"1g", "8g", "64g","512g", "4t",
"32t", "128t", "0",
"1", "64k", "64M"
};
public static void main(String[] args) throws Exception {
String appJar = JarBuilder.getOrCreateHelloJar();
for (String testEntry : testTable) {
System.out.println("sharedBaseAddress = " + testEntry);
OutputAnalyzer dumpOutput = TestCommon.dump(
appJar, new String[] {"Hello"}, "-XX:SharedBaseAddress=" + testEntry);
TestCommon.checkDump(dumpOutput, "Loading classes to share");
OutputAnalyzer execOutput = TestCommon.exec(appJar, "Hello");
TestCommon.checkExec(execOutput, "Hello World");
}
}
}

View File

@ -0,0 +1,79 @@
/*
* Copyright (c) 2014, 2017, 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
* @summary AppCDS handling of package.
* AppCDS does not support uncompressed oops
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @compile test-classes/PackageTest.java
* @compile test-classes/JimageClassPackage.java
* @run main SharedPackages
*/
import jdk.test.lib.process.OutputAnalyzer;
public class SharedPackages {
public static void main(String[] args) throws Exception {
JarBuilder.build("pkg", "p/PackageTest", "JimageClassPackage");
String appJar = TestCommon.getTestJar("pkg.jar");
TestCommon.testDump(appJar, TestCommon.list("p/PackageTest",
"java/util/Dictionary",
"sun/tools/javac/Main",
"jdk/nio/zipfs/ZipInfo",
"java/net/URL",
"sun/rmi/rmic/Main",
"com/sun/jndi/dns/DnsName"));
OutputAnalyzer output;
// Test 1: shared class from Jar on the -cp
output = TestCommon.exec(appJar, "-verbose:class", "p.PackageTest");
TestCommon.checkExec(output, "Expected package");
if (!TestCommon.isUnableToMap(output))
output.shouldContain("Package is not sealed");
// Test 2: shared classes from "modules" jimage
output = TestCommon.exec(appJar, "-verbose:class",
"JimageClassPackage");
if (!TestCommon.isUnableToMap(output)) {
output.shouldNotContain("Unexpected package");
output.shouldNotContain("Package is not sealed");
}
// Test 3: shared class from Jar on the -Xbootclasspath/a
TestCommon.dump(
appJar, TestCommon.list("p/PackageTest"), "-Xbootclasspath/a:" + appJar);
output = TestCommon.exec(appJar, "-Xbootclasspath/a:" + appJar, "p.PackageTest");
if (!TestCommon.isUnableToMap(output)) {
output.shouldNotContain("Unexpected package");
output.shouldContain("Package is not sealed");
}
}
}

View File

@ -0,0 +1,69 @@
/*
* Copyright (c) 2014, 2017, 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
* @summary AppCDS handling of signed JAR.
* AppCDS does not support uncompressed oops
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @compile test-classes/Hello.java
* @run main SignedJar
*/
import jdk.test.lib.process.OutputAnalyzer;
import java.io.File;
public class SignedJar {
public static void main(String[] args) throws Exception {
String unsignedJar = JarBuilder.getOrCreateHelloJar();
JarBuilder.signJar();
// Test class exists in signed JAR
String signedJar = TestCommon.getTestJar("signed_hello.jar");
OutputAnalyzer output;
output = TestCommon.dump(signedJar, TestCommon.list("Hello"));
TestCommon.checkDump(output, "Preload Warning: Skipping Hello from signed JAR");
// At runtime, the Hello class should be loaded from the jar file
// instead of from the shared archive since a class from a signed
// jar shouldn't be dumped into the archive.
output = TestCommon.exec(signedJar, "-verbose:class", "Hello");
String expectedOutput = ".class,load. Hello source: file:.*signed_hello.jar";
try {
output.shouldMatch(expectedOutput);
} catch (Exception e) {
TestCommon.checkCommonExecExceptions(output, e);
}
// Test class exists in both signed JAR and unsigned JAR
String jars = signedJar + System.getProperty("path.separator") + unsignedJar;
output = TestCommon.dump(jars, TestCommon.list("Hello"));
TestCommon.checkDump(output, "Preload Warning: Skipping Hello from signed JAR");
}
}

View File

@ -0,0 +1,107 @@
/*
* Copyright (c) 2014, 2017, 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
* @summary If -Djava.system.class.loader=xxx is specified in command-line, disable UseAppCDS
* AppCDS does not support uncompressed oops
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @library /test/lib
* @modules java.base/jdk.internal.misc
* jdk.jartool/sun.tools.jar
* @compile test-classes/TestClassLoader.java
* @compile test-classes/ReportMyLoader.java
* @compile test-classes/TrySwitchMyLoader.java
* @run main SpecifySysLoaderProp
*/
import java.io.*;
import jdk.test.lib.process.OutputAnalyzer;
public class SpecifySysLoaderProp {
public static void main(String[] args) throws Exception {
JarBuilder.build("sysloader", "TestClassLoader", "ReportMyLoader", "TrySwitchMyLoader");
String jarFileName = "sysloader.jar";
String appJar = TestCommon.getTestJar(jarFileName);
TestCommon.testDump(appJar, TestCommon.list("ReportMyLoader"));
String warning = "VM warning: UseAppCDS is disabled because the java.system.class.loader property is specified";
// (0) Baseline. Do not specify -Djava.system.class.loader
// The test class should be loaded from archive
OutputAnalyzer output = TestCommon.execCommon(
"-verbose:class",
"-cp", appJar,
"ReportMyLoader");
TestCommon.checkExec(output,
"[class,load] ReportMyLoader source: shared objects file",
"ReportMyLoader's loader = jdk.internal.loader.ClassLoaders$AppClassLoader@");
// (1) Try to execute the archive with -Djava.system.class.loader=no.such.Klass,
// it should fail
output = TestCommon.execCommon(
"-cp", appJar,
"-Djava.system.class.loader=no.such.Klass",
"ReportMyLoader");
try {
output.shouldContain(warning);
output.shouldContain("ClassNotFoundException: no.such.Klass");
} catch (Exception e) {
TestCommon.checkCommonExecExceptions(output, e);
}
// (2) Try to execute the archive with -Djava.system.class.loader=TestClassLoader,
// it should run, but AppCDS should be disabled
output = TestCommon.execCommon(
"-verbose:class",
"-cp", appJar,
"-Djava.system.class.loader=TestClassLoader",
"ReportMyLoader");
TestCommon.checkExec(output,
"ReportMyLoader's loader = jdk.internal.loader.ClassLoaders$AppClassLoader@", //<-this is still printed because TestClassLoader simply delegates to Launcher$AppLoader, but ...
"TestClassLoader.called = true", //<-but this proves that TestClassLoader was indeed called.
"TestClassLoader: loadClass(\"ReportMyLoader\","); //<- this also proves that TestClassLoader was indeed called.
try {
output.shouldMatch(".class,load. TestClassLoader source: file:");
output.shouldMatch(".class,load. ReportMyLoader source: file:.*" + jarFileName);
} catch (Exception e) {
TestCommon.checkCommonExecExceptions(output, e);
}
// (3) Try to change the java.system.class.loader programmatically after
// the app's main method is executed. This should have no effect in terms of
// changing or switching the actual system class loader that's already in use.
output = TestCommon.execCommon(
"-verbose:class",
"-cp", appJar,
"TrySwitchMyLoader");
TestCommon.checkExec(output,
"[class,load] ReportMyLoader source: shared objects file",
"TrySwitchMyLoader's loader = jdk.internal.loader.ClassLoaders$AppClassLoader@",
"ReportMyLoader's loader = jdk.internal.loader.ClassLoaders$AppClassLoader@",
"TestClassLoader.called = false");
}
}

View File

@ -0,0 +1,339 @@
/*
* Copyright (c) 2014, 2017, 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.
*
*/
import jdk.test.lib.Utils;
import jdk.test.lib.JDKToolFinder;
import jdk.test.lib.Platform;
import jdk.test.lib.cds.CDSOptions;
import jdk.test.lib.cds.CDSTestUtils;
import jdk.test.lib.process.ProcessTools;
import jdk.test.lib.process.OutputAnalyzer;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
/**
* This is a test utility class for common AppCDS test functionality.
*
* Various methods use (String ...) for passing VM options. Note that the order
* of the VM options are important in certain cases. Many methods take arguments like
*
* (String prefix[], String suffix[], String... opts)
*
* Note that the order of the VM options is:
*
* prefix + opts + suffix
*/
public class TestCommon extends CDSTestUtils {
private static final String JSA_FILE_PREFIX = System.getProperty("user.dir") +
File.separator + "appcds-";
private static final SimpleDateFormat timeStampFormat =
new SimpleDateFormat("HH'h'mm'm'ss's'SSS");
private static final String timeoutFactor =
System.getProperty("test.timeout.factor", "1.0");
private static String currentArchiveName;
// Call this method to start new archive with new unique name
public static void startNewArchiveName() {
deletePriorArchives();
currentArchiveName = JSA_FILE_PREFIX +
timeStampFormat.format(new Date()) + ".jsa";
}
// Call this method to get current archive name
public static String getCurrentArchiveName() {
return currentArchiveName;
}
// Attempt to clean old archives to preserve space
// Archives are large artifacts (20Mb or more), and much larger than
// most other artifacts created in jtreg testing.
// Therefore it is a good idea to clean the old archives when they are not needed.
// In most cases the deletion attempt will succeed; on rare occasion the
// delete operation will fail since the system or VM process still holds a handle
// to the file; in such cases the File.delete() operation will silently fail, w/o
// throwing an exception, thus allowing testing to continue.
public static void deletePriorArchives() {
File dir = new File(System.getProperty("user.dir"));
String files[] = dir.list();
for (String name : files) {
if (name.startsWith("appcds-") && name.endsWith(".jsa")) {
if (!(new File(dir, name)).delete())
System.out.println("deletePriorArchives(): delete failed for file " + name);
}
}
}
// Create AppCDS archive using most common args - convenience method
// Legacy name preserved for compatibility
public static OutputAnalyzer dump(String appJar, String appClasses[],
String... suffix) throws Exception {
return createArchive(appJar, appClasses, suffix);
}
// Create AppCDS archive using most common args - convenience method
public static OutputAnalyzer createArchive(String appJar, String appClasses[],
String... suffix) throws Exception {
AppCDSOptions opts = (new AppCDSOptions()).setAppJar(appJar)
.setAppClasses(appClasses);
opts.addSuffix(suffix);
return createArchive(opts);
}
// Create AppCDS archive using appcds options
public static OutputAnalyzer createArchive(AppCDSOptions opts)
throws Exception {
ArrayList<String> cmd = new ArrayList<String>();
File classList = makeClassList(opts.appClasses);
startNewArchiveName();
for (String p : opts.prefix) cmd.add(p);
if (opts.appJar != null) {
cmd.add("-cp");
cmd.add(opts.appJar);
} else {
cmd.add("-cp");
cmd.add("\"\"");
}
cmd.add("-Xshare:dump");
cmd.add("-Xlog:cds,cds+hashtables");
cmd.add("-XX:+UseAppCDS");
cmd.add("-XX:ExtraSharedClassListFile=" + classList.getPath());
if (opts.archiveName == null)
opts.archiveName = getCurrentArchiveName();
cmd.add("-XX:SharedArchiveFile=" + opts.archiveName);
for (String s : opts.suffix) cmd.add(s);
String[] cmdLine = cmd.toArray(new String[cmd.size()]);
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, cmdLine);
return executeAndLog(pb, "dump");
}
// Execute JVM using AppCDS archive with specified AppCDSOptions
public static OutputAnalyzer runWithArchive(AppCDSOptions opts)
throws Exception {
ArrayList<String> cmd = new ArrayList<String>();
for (String p : opts.prefix) cmd.add(p);
cmd.add("-Xshare:" + opts.xShareMode);
cmd.add("-XX:+UseAppCDS");
cmd.add("-showversion");
cmd.add("-XX:SharedArchiveFile=" + getCurrentArchiveName());
cmd.add("-Dtest.timeout.factor=" + timeoutFactor);
if (opts.appJar != null) {
cmd.add("-cp");
cmd.add(opts.appJar);
}
for (String s : opts.suffix) cmd.add(s);
String[] cmdLine = cmd.toArray(new String[cmd.size()]);
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, cmdLine);
return executeAndLog(pb, "exec");
}
public static OutputAnalyzer execCommon(String... suffix) throws Exception {
AppCDSOptions opts = (new AppCDSOptions());
opts.addSuffix(suffix);
return runWithArchive(opts);
}
public static OutputAnalyzer exec(String appJar, String... suffix) throws Exception {
AppCDSOptions opts = (new AppCDSOptions()).setAppJar(appJar);
opts.addSuffix(suffix);
return runWithArchive(opts);
}
public static OutputAnalyzer execAuto(String... suffix) throws Exception {
AppCDSOptions opts = (new AppCDSOptions());
opts.addSuffix(suffix).setXShareMode("auto");
return runWithArchive(opts);
}
public static OutputAnalyzer execOff(String... suffix) throws Exception {
AppCDSOptions opts = (new AppCDSOptions());
opts.addSuffix(suffix).setXShareMode("off");
return runWithArchive(opts);
}
public static OutputAnalyzer execModule(String prefix[], String upgrademodulepath, String modulepath,
String mid, String... testClassArgs)
throws Exception {
AppCDSOptions opts = (new AppCDSOptions());
opts.addPrefix(prefix);
if (upgrademodulepath == null) {
opts.addSuffix("-p", modulepath, "-m", mid);
} else {
opts.addSuffix("--upgrade-module-path", upgrademodulepath,
"-p", modulepath, "-m", mid);
}
opts.addSuffix(testClassArgs);
return runWithArchive(opts);
}
// A common operation: dump, then check results
public static OutputAnalyzer testDump(String appJar, String appClasses[],
String... suffix) throws Exception {
OutputAnalyzer output = dump(appJar, appClasses, suffix);
output.shouldContain("Loading classes to share");
output.shouldHaveExitValue(0);
return output;
}
/**
* Simple test -- dump and execute appJar with the given appClasses in classlist.
*/
public static OutputAnalyzer test(String appJar, String appClasses[], String... args)
throws Exception {
testDump(appJar, appClasses);
OutputAnalyzer output = exec(appJar, args);
return checkExec(output);
}
public static OutputAnalyzer checkExecReturn(OutputAnalyzer output, int ret,
boolean checkContain, String... matches) throws Exception {
try {
for (String s : matches) {
if (checkContain) {
output.shouldContain(s);
} else {
output.shouldNotContain(s);
}
}
output.shouldHaveExitValue(ret);
} catch (Exception e) {
checkCommonExecExceptions(output, e);
}
return output;
}
// Convenience concatenation utils
public static String[] list(String ...args) {
return args;
}
public static String[] list(String arg, int count) {
ArrayList<String> stringList = new ArrayList<String>();
for (int i = 0; i < count; i++) {
stringList.add(arg);
}
String outputArray[] = stringList.toArray(new String[stringList.size()]);
return outputArray;
}
public static String[] concat(String... args) {
return list(args);
}
public static String[] concat(String prefix[], String... extra) {
ArrayList<String> list = new ArrayList<String>();
for (String s : prefix) {
list.add(s);
}
for (String s : extra) {
list.add(s);
}
return list.toArray(new String[list.size()]);
}
// ===================== Concatenate paths
public static String concatPaths(String... paths) {
String prefix = "";
String s = "";
for (String p : paths) {
s += prefix;
s += p;
prefix = File.pathSeparator;
}
return s;
}
public static String getTestJar(String jar) {
File jarFile = CDSTestUtils.getTestArtifact(jar, true);
if (!jarFile.isFile()) {
throw new RuntimeException("Not a regular file: " + jarFile.getPath());
}
return jarFile.getPath();
}
public static String getTestDir(String d) {
File dirFile = CDSTestUtils.getTestArtifact(d, true);
if (!dirFile.isDirectory()) {
throw new RuntimeException("Not a directory: " + dirFile.getPath());
}
return dirFile.getPath();
}
// Returns true if custom loader is supported, based on a platform.
// Custom loader AppCDS is only supported for Linux-x64 and Solaris.
public static boolean isCustomLoaderSupported() {
boolean isLinux = Platform.isLinux();
boolean isX64 = Platform.isX64();
boolean isSolaris = Platform.isSolaris();
System.out.println("isCustomLoaderSupported: isX64 = " + isX64);
System.out.println("isCustomLoaderSupported: isLinux = " + isLinux);
System.out.println("isCustomLoaderSupported: isSolaris = " + isSolaris);
return ((isX64 && isLinux) || isSolaris);
}
}

View File

@ -0,0 +1,105 @@
/*
* Copyright (c) 2014, 2017, 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
* @summary ensure -XX:+TraceClassPaths showing entire expecting app classpath
* AppCDS does not support uncompressed oops
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @compile test-classes/Hello.java
* @run main TraceLongClasspath
*/
import java.io.File;
import jdk.test.lib.process.OutputAnalyzer;
public class TraceLongClasspath {
final static String ps = File.pathSeparator;
public static void main(String[] args) throws Exception {
String appJar = JarBuilder.getOrCreateHelloJar();
String longClassPath =
"/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/abc/abc/modules/user-patch.jar" + ps +
"/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/abc/abc/modules/abc-startup.jar" + ps +
"/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/foobar_common/modules/features/com.foobar.db.jdbc7-dms.jar" + ps +
"/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/jdk/lib/tools.jar" + ps +
"/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/aaserver/server/lib/someapps.jar" + ps +
"/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/aaserver/../foobar_common/modules/net.xy.batcontrib_1.1.0.0_1-0b3/lib/bat-contrib.jar" + ps +
"/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/aaserver/modules/features/foobar.aas.common.kkkkkkkkkkk.jar" + ps +
"/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/abc/abc/modules/foobar.abc.common.adapters_11.1.1/foobar.abc.common.adapters.jar" + ps +
"/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/abc/abc/modules/foobar.plane.adapter_12.1.3/foobar.plane.adapter.jar" + ps +
"/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/abc/lib/ccccccccar-common.jar" + ps +
"/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/foobar_common/communications/modules/config.jar" + ps +
"/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/foobar_common/communications/modules/userprefs-config.jar" + ps +
"/scratch/xxxx/yyyy/XXXXXX/aaaaaaaa/xxxxxxx/xxxxxxxx.us.foobar.com/CommonDomain/config/abc-infra" + ps +
"/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/abc/abc/modules/qqqqqq-all-1.6.5.jar" + ps +
"/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/abc/abc/modules/foobar.abc.thread_11.1.1/foobar.abc.thread.jar" + ps +
"/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/abc/abc/modules/foobar.abc.thread_11.1.1/thread-rrrrrrr-ext-aas.jar" + ps +
"/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/abc/abc/modules/foobar.abc.adapter_11.1.1/foobar.abc.adapter.jar" + ps +
"/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/abc/abc/modules/foobar.abc.ccc_11.1.1/foobar.abc.ccc.jar" + ps +
"/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/bbb/lib/commons-configuration.jar" + ps +
"/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/bbb/lib/commons-lang.jar" + ps +
"/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/bbb/lib/commons-logging.jar" + ps +
"/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/foobar_common/modules/foobar.wccore/foobar-ppppppp-api.jar" + ps +
"/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/foobar_common/modules/foobar.ooo_12.1.3/ooo-manifest.jar" + ps +
"/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/foobar_common/modules/internal/features/rrr_aaxyxx_foobar.rrr.aas.classpath.jar" + ps +
"/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/abc/abc/modules/foobar.abc.thread_11.1.1/rrrrrrrr-api.jar" + ps +
"/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/abc/abc/modules/commons-xxx-1.1.jar" + ps +
"/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/abc/abc/modules/foobar.abc.mgmt_11.1.1/abc-infra-mgmt.jar" + ps +
"/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/foobar_common/eee/archives/eee-eee.jar" + ps +
"/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/aaserver/common/march/lib/marchnet.jar" + ps +
"/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/aaserver/common/march/lib/marchclient.jar" + ps +
"/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/aaserver/common/march/lib/march.jar" + ps +
"/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/wwcontent/cde/iii/jlib/iiiloader.jar" + ps +
"/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/wwcontent/cde/iii/components/xxxxxxyyzzzzz/classes-xxxxxxyyzzzzz.jar" + ps +
"/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/wwcontent/cde/iii/components/mmmmmmm/lib/abc_core.jar" + ps +
"/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/wwcontent/cde/iii/components/mmmmmmm/lib/abc_codec.jar" + ps +
"/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/wwcontent/cde/iii/components/mmmmmmm/lib/abc_imageio.jar" + ps +
"/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/jdk/lib/tools.jar" + ps +
"/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/foobar_common/modules/foobar.ooo_12.1.3/ooo-manifest.jar";
longClassPath += ps + appJar;
// Dump an archive with a specified JAR file in -classpath
TestCommon.testDump(longClassPath, TestCommon.list("Hello"));
// Then try to execute the archive with a different classpath and with -XX:+TraceClassPaths.
// The diagnosis "expecting" app classpath trace should show the entire classpath.
OutputAnalyzer output = TestCommon.execCommon(
"-XX:+TraceClassPaths",
"-cp", appJar,
"Hello");
output.shouldContain("Unable to use shared archive");
output.shouldContain("shared class paths mismatch");
// the "expecting" app classpath from -XX:+TraceClassPaths should not
// be truncated
output.shouldContain(longClassPath);
output.shouldHaveExitValue(1);
}
}

View File

@ -0,0 +1,228 @@
/*
* Copyright (c) 2014, 2017, 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
* @summary Testing use of UseAppCDS flag
* AppCDS does not support uncompressed oops
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @build UseAppCDS_Test
* @run main UseAppCDS
*/
import jdk.test.lib.JDKToolLauncher;
import jdk.test.lib.cds.CDSTestUtils;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
import java.util.ArrayList;
import java.util.List;
import java.io.*;
public class UseAppCDS {
// Class UseAppCDS_Test is loaded by the App loader
static final String TEST_OUT = "UseAppCDS_Test.main--executed";
private static final String TESTJAR = "./test.jar";
private static final String TESTNAME = "UseAppCDS_Test";
private static final String TESTCLASS = TESTNAME + ".class";
private static final String CLASSES_DIR = System.getProperty("test.classes", ".");
private static final String CLASSLIST_FILE = "./UseAppCDS.classlist";
private static final String ARCHIVE_FILE = "./shared.jsa";
private static final String BOOTCLASS = "java.lang.Class";
public static void main(String[] args) throws Exception {
// First create a jar file for the application "test" class
JDKToolLauncher jar = JDKToolLauncher.create("jar")
.addToolArg("-cf")
.addToolArg(TESTJAR)
.addToolArg("-C")
.addToolArg(CLASSES_DIR)
.addToolArg(TESTCLASS);
ProcessBuilder pb = new ProcessBuilder(jar.getCommand());
TestCommon.executeAndLog(pb, "jar01").shouldHaveExitValue(0);
pb = new ProcessBuilder(jar.getCommand());
TestCommon.executeAndLog(pb, "jar02").shouldHaveExitValue(0);
// In all tests the BOOTCLASS should be loaded/dumped/used
// Test 1: No AppCDS - dumping loaded classes excludes the "test" classes
dumpLoadedClasses(false, new String[] { BOOTCLASS },
new String[] { TESTNAME });
// Test 2: AppCDS - dumping loaded classes includes "test" classes
dumpLoadedClasses(true, new String[] { BOOTCLASS, TESTNAME },
new String[0]);
// Next tests rely on the classlist we just dumped
// Test 3: No AppCDS - "test" classes in classlist ignored when dumping
dumpArchive(false, new String[] { BOOTCLASS },
new String[] { TESTNAME});
// Test 4: AppCDS - "test" classes in classlist are dumped
dumpArchive(true, new String[] { BOOTCLASS, TESTNAME },
new String[0]);
// Next tests rely on the archive we just dumped
// Test 5: No AppCDS - Using archive containing "test" classes ignores them
useArchive(false, new String[] { BOOTCLASS },
new String[] { TESTNAME });
// Test 6: AppCDS - Using archive containing "test" classes loads them
useArchive(true, new String[] { BOOTCLASS, TESTNAME },
new String[0]);
}
public static List<String> toClassNames(String filename) throws IOException {
ArrayList<String> classes = new ArrayList<>();
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(filename)));
for (; ; ) {
String line = br.readLine();
if (line == null)
break;
classes.add(line.replaceAll("/", "."));
}
return classes;
}
static void dumpLoadedClasses(boolean useAppCDS, String[] expectedClasses,
String[] unexpectedClasses) throws Exception {
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
true,
"-XX:DumpLoadedClassList=" + CLASSLIST_FILE,
"-cp",
TESTJAR,
useAppCDS ? "-XX:+UseAppCDS" : "-XX:-UseAppCDS",
TESTNAME,
TEST_OUT);
OutputAnalyzer output = TestCommon.executeAndLog(pb, "dump-loaded-classes")
.shouldHaveExitValue(0).shouldContain(TEST_OUT);
List<String> dumpedClasses = toClassNames(CLASSLIST_FILE);
for (String clazz : expectedClasses) {
if (!dumpedClasses.contains(clazz)) {
throw new RuntimeException(clazz + " missing in " +
CLASSLIST_FILE);
}
}
for (String clazz : unexpectedClasses) {
if (dumpedClasses.contains(clazz)) {
throw new RuntimeException("Unexpectedly found " + clazz +
" in " + CLASSLIST_FILE);
}
}
}
static void dumpArchive(boolean useAppCDS, String[] expectedClasses,
String[] unexpectedClasses) throws Exception {
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
true,
useAppCDS ? "-XX:-UnlockDiagnosticVMOptions" :
"-XX:+UnlockDiagnosticVMOptions",
"-cp",
TESTJAR,
useAppCDS ? "-XX:+UseAppCDS" : "-XX:-UseAppCDS",
"-XX:SharedClassListFile=" + CLASSLIST_FILE,
"-XX:SharedArchiveFile=" + ARCHIVE_FILE,
"-Xlog:cds",
"-Xshare:dump");
OutputAnalyzer output = TestCommon.executeAndLog(pb, "dump-archive")
.shouldHaveExitValue(0);
for (String clazz : expectedClasses) {
String failed = "Preload Warning: Cannot find " + clazz;
output.shouldNotContain(failed);
}
for (String clazz : unexpectedClasses) {
String failed = "Preload Warning: Cannot find " + clazz;
output.shouldContain(failed);
}
}
static void useArchive(boolean useAppCDS, String[] expectedClasses,
String[] unexpectedClasses) throws Exception {
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
true,
useAppCDS ? "-XX:-UnlockDiagnosticVMOptions" :
"-XX:+UnlockDiagnosticVMOptions",
"-cp",
TESTJAR,
useAppCDS ? "-XX:+UseAppCDS" : "-XX:-UseAppCDS",
"-XX:SharedArchiveFile=" + ARCHIVE_FILE,
"-verbose:class",
"-Xshare:on",
TESTNAME,
TEST_OUT );
OutputAnalyzer output = TestCommon.executeAndLog(pb, "use-archive");
if (CDSTestUtils.isUnableToMap(output))
System.out.println("Unable to map: test case skipped");
else
output.shouldHaveExitValue(0).shouldContain(TEST_OUT);
// Quote the class name in the regex as it may contain $
String prefix = ".class,load. ";
String archive_suffix = ".*source: shared objects file.*";
String jar_suffix = ".*source: .*\\.jar";
for (String clazz : expectedClasses) {
String pattern = prefix + clazz + archive_suffix;
try {
output.shouldMatch(pattern);
} catch (Exception e) {
TestCommon.checkCommonExecExceptions(output, e);
}
}
for (String clazz : unexpectedClasses) {
String pattern = prefix + clazz + archive_suffix;
try {
output.shouldNotMatch(pattern);
} catch (Exception e) {
TestCommon.checkCommonExecExceptions(output, e);
}
pattern = prefix + clazz + jar_suffix;
try {
output.shouldMatch(pattern);
} catch (Exception e) {
TestCommon.checkCommonExecExceptions(output, e);
}
}
}
}

View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2014, 2017, 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 class UseAppCDS_Test {
// args are from UseAppCDS:
// args[0] = TEST_OUT
public static void main(String[] args) {
System.out.println(args[0]);
}
}

View File

@ -0,0 +1,343 @@
/*
* Copyright (c) 2014, 2017, 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.
*
*/
import java.io.File;
import java.io.FileOutputStream;
import jdk.test.lib.process.OutputAnalyzer;
import java.nio.file.Files;
import java.util.*;
import jdk.internal.org.objectweb.asm.*;
/**
* The testsets contained in this class are executed by ./VerifierTest_*.java, so that
* individual testsets can be executed in parallel to shorten the total time required.
*/
public class VerifierTest implements Opcodes {
// Test verification settings for dumping & runtime
static final String VFY_ALL = "-Xverify:all";
static final String VFY_REMOTE = "-Xverify:remote"; // default
static final String VFY_NONE = "-Xverify:none";
static final String ERR =
"ERROR: class VerifierTestC was loaded unexpectedly";
static final String MAP_FAIL =
"shared archive file was created with less restrictive verification setting";
static final String VFY_ERR = "java.lang.VerifyError";
enum Testset1Part {
A, B
}
public static void main(String[] args) throws Exception {
String subCaseId = args[0];
String jarName_verifier_test_tmp = "verifier_test_tmp" + "_" + subCaseId;
String jarName_verifier_test = "verifier_test" + "_" + subCaseId;
String jarName_greet = "greet" + "_" + subCaseId;
String jarName_hi = "hi" + "_" + subCaseId;
JarBuilder.build(jarName_verifier_test_tmp, "VerifierTest0", "VerifierTestA",
"VerifierTestB", "VerifierTestC", "VerifierTestD", "VerifierTestE",
"UnverifiableBase", "UnverifiableIntf", "UnverifiableIntfSub");
JarBuilder.build(jarName_greet, "Greet");
JarBuilder.build(jarName_hi, "Hi", "Hi$MyClass");
File dir = new File(System.getProperty("test.classes", "."));
File jarSrcFile = new File(dir, jarName_verifier_test_tmp + ".jar");
File jarFile = new File(dir, jarName_verifier_test + ".jar");
String jar = jarFile.getPath();
if (!jarFile.exists() || jarFile.lastModified() < jarSrcFile.lastModified()) {
createTestJarFile(jarSrcFile, jarFile);
} else {
System.out.println("Already up-to-date: " + jarFile);
}
String noAppClasses[] = TestCommon.list("");
String appClasses[] = TestCommon.list("UnverifiableBase",
"UnverifiableIntf",
"UnverifiableIntfSub",
"VerifierTestA",
"VerifierTestB",
"VerifierTestC",
"VerifierTestD",
"VerifierTestE",
"VerifierTest0");
switch (subCaseId) {
case "0": testset_0(jar, noAppClasses, appClasses); return;
case "1A": testset_1(jar, noAppClasses, appClasses, Testset1Part.A); return;
case "1B": testset_1(jar, noAppClasses, appClasses, Testset1Part.B); return;
case "2": testset_2(jarName_greet, jarName_hi); return;
default:
throw new RuntimeException("Unknown option: " + subCaseId);
}
}
static void testset_0(String jar, String[] noAppClasses, String[] appClasses) throws Exception {
// Dumping should fail if the IgnoreUnverifiableClassesDuringDump
// option is not enabled.
OutputAnalyzer output = TestCommon.dump(jar, appClasses,
"-XX:+UnlockDiagnosticVMOptions",
"-XX:-IgnoreUnverifiableClassesDuringDump");
output.shouldContain("Please remove the unverifiable classes");
output.shouldHaveExitValue(1);
// By default, bad classes should be ignored during dumping.
TestCommon.testDump(jar, appClasses);
}
static void testset_1(String jar, String[] noAppClasses, String[] appClasses, Testset1Part part)
throws Exception
{
String config[][] = {
// {dump_list, dumptime_verification_setting,
// runtime_verification_setting, runtime_output},
// Dump app/ext with -Xverify:remote
{"app", VFY_REMOTE, VFY_REMOTE, VFY_ERR},
{"app", VFY_REMOTE, VFY_ALL, MAP_FAIL},
{"app", VFY_REMOTE, VFY_NONE, ERR },
// Dump app/ext with -Xverify:all
{"app", VFY_ALL, VFY_REMOTE, VFY_ERR },
{"app", VFY_ALL, VFY_ALL, VFY_ERR },
{"app", VFY_ALL, VFY_NONE, ERR },
// Dump app/ext with -Xverify:none
{"app", VFY_NONE, VFY_REMOTE, MAP_FAIL},
{"app", VFY_NONE, VFY_ALL, MAP_FAIL},
{"app", VFY_NONE, VFY_NONE, ERR },
// Dump sys only with -Xverify:remote
{"noApp", VFY_REMOTE, VFY_REMOTE, VFY_ERR},
{"noApp", VFY_REMOTE, VFY_ALL, VFY_ERR},
{"noApp", VFY_REMOTE, VFY_NONE, ERR},
// Dump sys only with -Xverify:all
{"noApp", VFY_ALL, VFY_REMOTE, VFY_ERR},
{"noApp", VFY_ALL, VFY_ALL, VFY_ERR},
{"noApp", VFY_ALL, VFY_NONE, ERR},
// Dump sys only with -Xverify:none
{"noApp", VFY_NONE, VFY_REMOTE, VFY_ERR},
{"noApp", VFY_NONE, VFY_ALL, VFY_ERR},
{"noApp", VFY_NONE, VFY_NONE, ERR},
};
int loop_start, loop_stop;
// Further break down testset_1 into two parts (to be invoked from VerifierTest_1A.java
// and VerifierTest_1B.java) to improve parallel test execution time.
switch (part) {
case A:
loop_start = 0;
loop_stop = 9;
break;
case B:
default:
assert part == Testset1Part.B;
loop_start = 9;
loop_stop = config.length;
break;
}
String prev_dump_setting = "";
for (int i = loop_start; i < loop_stop; i ++) {
String dump_list[] = config[i][0].equals("app") ? appClasses :
noAppClasses;
String dump_setting = config[i][1];
String runtime_setting = config[i][2];
String runtime_output = config[i][3];
System.out.println("Test case [" + i + "]: dumping " + config[i][0] +
" with " + dump_setting +
", run with " + runtime_setting);
if (!dump_setting.equals(prev_dump_setting)) {
OutputAnalyzer dumpOutput = TestCommon.dump(
jar, dump_list, dump_setting,
// FIXME: the following options are for working around a GC
// issue - assert failure when dumping archive with the -Xverify:all
"-Xms256m",
"-Xmx256m");
}
OutputAnalyzer runtimeOutput = TestCommon.execCommon(
"-cp", jar,
runtime_setting,
"VerifierTest0");
try {
runtimeOutput.shouldContain(runtime_output);
} catch (RuntimeException re) {
// Check if the failure is due to archive mapping failure.
// If not, a RuntimeException will be thrown.
runtimeOutput.shouldContain("Unable to use shared archive");
}
prev_dump_setting = dump_setting;
}
}
static void testset_2(String jarName_greet, String jarName_hi) throws Exception {
String appClasses[];
String jar;
// The following section is for testing the scenarios where
// the classes are verifiable during dump time.
appClasses = TestCommon.list("Hi",
"Greet",
"Hi$MyClass");
jar = TestCommon.getTestJar(jarName_hi + ".jar") + File.pathSeparator +
TestCommon.getTestJar(jarName_greet + ".jar");
final String PASS_RESULT = "Hi, how are you?";
String config2[][] = {
// {dump_list, dumptime_verification_setting,
// runtime_verification_setting, runtime_output},
// Dump app/ext with -Xverify:remote
{"app", VFY_REMOTE, VFY_REMOTE, PASS_RESULT},
{"app", VFY_REMOTE, VFY_ALL, MAP_FAIL},
{"app", VFY_REMOTE, VFY_NONE, PASS_RESULT },
// Dump app/ext with -Xverify:all
{"app", VFY_ALL, VFY_REMOTE, PASS_RESULT },
{"app", VFY_ALL, VFY_ALL, PASS_RESULT },
{"app", VFY_ALL, VFY_NONE, PASS_RESULT },
// Dump app/ext with -Xverify:none
{"app", VFY_NONE, VFY_REMOTE, MAP_FAIL},
{"app", VFY_NONE, VFY_ALL, MAP_FAIL},
{"app", VFY_NONE, VFY_NONE, PASS_RESULT },
};
for (int i = 0; i < config2.length; i ++) {
// config2[i][0] is always set to "app" in this test
String dump_setting = config2[i][1];
String runtime_setting = config2[i][2];
String runtime_output = config2[i][3];
System.out.println("Test case [" + i + "]: dumping " + config2[i][0] +
" with " + dump_setting +
", run with " + runtime_setting);
OutputAnalyzer dumpOutput = TestCommon.dump(
jar, appClasses, dump_setting,
"-XX:+UnlockDiagnosticVMOptions",
// FIXME: the following options are for working around a GC
// issue - assert failure when dumping archive with the -Xverify:all
"-Xms256m",
"-Xmx256m");
OutputAnalyzer runtimeOutput = TestCommon.execCommon(
"-cp", jar,
runtime_setting,
"Hi");
try {
runtimeOutput.shouldContain(runtime_output);
} catch (RuntimeException re) {
// Check if the failure is due to archive mapping failure.
// If not, a RuntimeException will be thrown.
runtimeOutput.shouldContain("Unable to use shared archive");
}
}
}
static void createTestJarFile(File jarSrcFile, File jarFile) throws Exception {
jarFile.delete();
Files.copy(jarSrcFile.toPath(), jarFile.toPath());
File dir = new File(System.getProperty("test.classes", "."));
File outdir = new File(dir, "verifier_test_classes");
outdir.mkdir();
writeClassFile(new File(outdir, "UnverifiableBase.class"), makeUnverifiableBase());
writeClassFile(new File(outdir, "UnverifiableIntf.class"), makeUnverifiableIntf());
JarBuilder.update(jarFile.getPath(), outdir.getPath());
}
static void writeClassFile(File file, byte bytecodes[]) throws Exception {
try (FileOutputStream fos = new FileOutputStream(file)) {
fos.write(bytecodes);
}
}
// This was obtained using JDK8: java jdk.internal.org.objectweb.asm.util.ASMifier tmpclasses/UnverifiableBase.class
static byte[] makeUnverifiableBase() throws Exception {
ClassWriter cw = new ClassWriter(0);
FieldVisitor fv;
MethodVisitor mv;
AnnotationVisitor av0;
cw.visit(V1_6, ACC_SUPER, "UnverifiableBase", null, "java/lang/Object", null);
{
fv = cw.visitField(ACC_FINAL + ACC_STATIC, "x", "LVerifierTest;", null, null);
fv.visitEnd();
}
{
mv = cw.visitMethod(0, "<init>", "()V", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null);
mv.visitCode();
//WAS mv.visitTypeInsn(NEW, "VerifierTest");
mv.visitTypeInsn(NEW, "java/lang/Object");
mv.visitInsn(DUP);
mv.visitMethodInsn(INVOKESPECIAL, "VerifierTest0", "<init>", "()V", false);
mv.visitFieldInsn(PUTSTATIC, "UnverifiableBase", "x", "LVerifierTest;");
mv.visitInsn(RETURN);
mv.visitMaxs(2, 0);
mv.visitEnd();
}
cw.visitEnd();
return cw.toByteArray();
}
// This was obtained using JDK8: java jdk.internal.org.objectweb.asm.util.ASMifier tmpclasses/UnverifiableIntf.class
static byte[] makeUnverifiableIntf() throws Exception {
ClassWriter cw = new ClassWriter(0);
FieldVisitor fv;
MethodVisitor mv;
AnnotationVisitor av0;
cw.visit(V1_6, ACC_ABSTRACT + ACC_INTERFACE, "UnverifiableIntf", null, "java/lang/Object", null);
{
fv = cw.visitField(ACC_PUBLIC + ACC_FINAL + ACC_STATIC, "x", "LVerifierTest0;", null, null);
fv.visitEnd();
}
{
mv = cw.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null);
mv.visitCode();
//WAS mv.visitTypeInsn(NEW, "VerifierTest");
mv.visitTypeInsn(NEW, "java/lang/Object");
mv.visitInsn(DUP);
mv.visitMethodInsn(INVOKESPECIAL, "VerifierTest0", "<init>", "()V", false);
mv.visitFieldInsn(PUTSTATIC, "UnverifiableIntf", "x", "LVerifierTest0;");
mv.visitInsn(RETURN);
mv.visitMaxs(2, 0);
mv.visitEnd();
}
cw.visitEnd();
return cw.toByteArray();
}
}

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2015, 2017, 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
* @summary Unverfiable app classes should not be archived.
* AppCDS does not support uncompressed oops
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @library /test/lib
* @modules java.base/jdk.internal.misc
* @modules jdk.jartool/sun.tools.jar
* java.base/jdk.internal.org.objectweb.asm
* @compile test-classes/Greet.java
* @compile test-classes/Hi.java
* @compile test-classes/VerifierTest0.java
* @run main/othervm/timeout=3600 VerifierTest 0
*/

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2015, 2017, 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
* @summary Unverfiable app classes should not be archived.
* AppCDS does not support uncompressed oops
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @library /test/lib
* @modules java.base/jdk.internal.misc
* @modules jdk.jartool/sun.tools.jar
* java.base/jdk.internal.org.objectweb.asm
* @compile test-classes/Greet.java
* @compile test-classes/Hi.java
* @compile test-classes/VerifierTest0.java
* @run main/othervm/timeout=3600 VerifierTest 1A
*/

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2015, 2017, 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
* @summary Unverfiable app classes should not be archived.
* AppCDS does not support uncompressed oops
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @library /test/lib
* @modules java.base/jdk.internal.misc
* @modules jdk.jartool/sun.tools.jar
* java.base/jdk.internal.org.objectweb.asm
* @compile test-classes/Greet.java
* @compile test-classes/Hi.java
* @compile test-classes/VerifierTest0.java
* @run main/othervm/timeout=3600 VerifierTest 1B
*/

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2015, 2017, 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
* @summary Unverfiable app classes should not be archived.
* AppCDS does not support uncompressed oops
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @library /test/lib
* @modules java.base/jdk.internal.misc
* @modules jdk.jartool/sun.tools.jar
* java.base/jdk.internal.org.objectweb.asm
* @compile test-classes/Greet.java
* @compile test-classes/Hi.java
* @compile test-classes/VerifierTest0.java
* @run main/othervm/timeout=3600 VerifierTest 2
*/

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2016, 2017, 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
* @summary Test 'iload_w' bytecode in shared class
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @compile test-classes/Iloadw.jasm
* @compile test-classes/IloadwMain.java
* @run main WideIloadTest
*/
import jdk.test.lib.process.OutputAnalyzer;
public class WideIloadTest {
public static void main(String args[]) throws Exception {
JarBuilder.build("iload_w", "Iloadw", "IloadwMain");
String appJar = TestCommon.getTestJar("iload_w.jar");
OutputAnalyzer dumpOutput = TestCommon.dump(appJar, TestCommon.list(
"Iloadw", "IloadwMain"));
TestCommon.checkDump(dumpOutput);
OutputAnalyzer execOutput = TestCommon.exec(appJar, "IloadwMain");
TestCommon.checkExec(execOutput, "Passed");
}
}

View File

@ -0,0 +1,56 @@
/*
* Copyright (c) 2014, 2017, 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
* @summary classpath mismatch between dump time and execution time
* AppCDS does not support uncompressed oops
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @compile test-classes/Hello.java
* @run main WrongClasspath
*/
import jdk.test.lib.process.OutputAnalyzer;
public class WrongClasspath {
public static void main(String[] args) throws Exception {
String appJar = JarBuilder.getOrCreateHelloJar();
// Dump an archive with a specified JAR file in -classpath
TestCommon.testDump(appJar, TestCommon.list("Hello"));
// Then try to execute the archive without -classpath -- it should fail
OutputAnalyzer output = TestCommon.execCommon(
/* "-cp", appJar, */ // <- uncomment this and the execution should succeed
"Hello");
output.shouldContain("Unable to use shared archive");
output.shouldContain("shared class paths mismatch");
output.shouldHaveExitValue(1);
}
}

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2015, 2017, 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
* @summary Test -Xshare:auto for AppCDS
* AppCDS does not support uncompressed oops
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @compile test-classes/Hello.java
* @run main XShareAutoWithChangedJar
*/
import jdk.test.lib.process.OutputAnalyzer;
public class XShareAutoWithChangedJar {
public static void main(String[] args) throws Exception {
String appJar = JarBuilder.build("XShareAutoWithChangedJar", "Hello");
// 1. dump
OutputAnalyzer output = TestCommon.dump(appJar, TestCommon.list("Hello"));
TestCommon.checkDump(output);
// 2. change the jar
JarBuilder.build("XShareAutoWithChangedJar", "Hello");
// 3. exec
output = TestCommon.execAuto("-cp", appJar, "Hello");
output.shouldContain("Hello World");
}
}

View File

@ -0,0 +1,69 @@
/*
* Copyright (c) 2017, 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
* @summary Test resolved_references
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @requires (sun.arch.data.model == "64")
* @requires ((os.family == "linux") & (os.arch=="amd64")) | (os.family == "solaris")
* @requires (vm.gc=="null")
* @library /test/lib /test/hotspot/jtreg/runtime/appcds
* @modules java.base/jdk.internal.misc
* @modules java.management
* jdk.jartool/sun.tools.jar
* @build sun.hotspot.WhiteBox
* @compile CheckCachedResolvedReferencesApp.java
* @compile ../test-classes/Hello.java
* @run main ClassFileInstaller -jar app.jar CheckCachedResolvedReferencesApp
* @run main ClassFileInstaller -jar hello.jar Hello
* @run main ClassFileInstaller -jar WhiteBox.jar sun.hotspot.WhiteBox
* @run main CheckCachedResolvedReferences
*/
import jdk.test.lib.process.OutputAnalyzer;
import sun.hotspot.WhiteBox;
public class CheckCachedResolvedReferences {
public static void main(String[] args) throws Exception {
String wbJar = ClassFileInstaller.getJarPath("WhiteBox.jar");
String use_whitebox_jar = "-Xbootclasspath/a:" + wbJar;
String appJar = ClassFileInstaller.getJarPath("app.jar");
String helloJarPath = ClassFileInstaller.getJarPath("hello.jar");
String classlist[] = new String[] {
"CheckCachedResolvedReferencesApp",
"java/lang/Object id: 1",
"Hello id: 2 super: 1 source: " + helloJarPath
};
TestCommon.testDump(appJar, classlist, use_whitebox_jar);
OutputAnalyzer output = TestCommon.exec(appJar, use_whitebox_jar,
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+WhiteBoxAPI",
"CheckCachedResolvedReferencesApp",
helloJarPath);
TestCommon.checkExec(output);
}
}

View File

@ -0,0 +1,77 @@
/*
* Copyright (c) 2017, 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.
*
*/
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import sun.hotspot.WhiteBox;
public class CheckCachedResolvedReferencesApp {
public static void main(String args[]) throws Exception {
String path = args[0];
URL url = new File(path).toURI().toURL();
URL[] urls = new URL[] {url};
URLClassLoader loader = new URLClassLoader(urls);
Class hello = loader.loadClass("Hello");
System.out.println("Loaded " + hello + " from " + url + " using loader " + loader);
WhiteBox wb = WhiteBox.getWhiteBox();
if (!wb.areOpenArchiveHeapObjectsMapped()) {
System.out.println("Archived open_archive_heap objects are not mapped.");
System.out.println("This may happen during normal operation. Test Skipped.");
return;
}
// CheckCachedResolvedReferencesApp is shared class and loaded by the
// AppClassLoader. It should have cached resolved_references.
if (wb.isSharedClass(CheckCachedResolvedReferencesApp.class)) {
Object refs1 = wb.getResolvedReferences(CheckCachedResolvedReferencesApp.class);
if (refs1 != null && wb.isShared(refs1)) {
System.out.println(
"resolved references from CheckCachedResolvedReferencesApp is cached");
} else {
throw new RuntimeException(
"FAILED. CheckCachedResolvedReferencesApp has no cached resolved references");
}
}
// Hello is shared class and loaded by the 'loader' defined in current app.
// It should not have cached resolved_references.
if (wb.isSharedClass(hello)) {
Object refs2 = wb.getResolvedReferences(hello);
if (refs2 != null) {
if (!wb.isShared(refs2)) {
System.out.println("resolved references from hello is not cached");
} else {
throw new RuntimeException(
"FAILED. Hello has unexpected cached resolved references");
}
} else {
throw new RuntimeException("FAILED. Hello has no resolved references");
}
}
}
}

View File

@ -0,0 +1,3 @@
VERSION: 1.0
@SECTION: String
26: shared_string_from_MyInner

View File

@ -0,0 +1,63 @@
/*
* Copyright (c) 2017, 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
* @summary Dump time should not crash if any class with shared strings fails verification due to missing dependencies.
* @bug 8186789
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @requires (sun.arch.data.model != "32") & (os.family != "windows")
* @requires (vm.gc=="null")
* @library /test/lib /test/hotspot/jtreg/runtime/appcds
* @modules java.base/jdk.internal.misc
* @modules java.management
* jdk.jartool/sun.tools.jar
* @compile MyOuter.java MyException.java
* @run main DumpTimeVerifyFailure
*/
import jdk.test.lib.process.OutputAnalyzer;
public class DumpTimeVerifyFailure {
public static void main(String[] args) throws Exception {
// App classes (see MyOuter.java):
// MyOuter
// MyInnder$MyOuter extends MyOuter
// MyException
//
// MyOuter$MyInner.test() throws MyException.
// The missingMyException.jar file only includes MyOuter and
// MyOuter$MyInner classes, but not the MyException class.
// At dump time, MyOuter and MyOuter$MyInner classes fail
// verification due to missing MyException class.
String[] ARCHIVE_CLASSES = {"MyOuter", "MyOuter$MyInner"};
String appJar = JarBuilder.build("missingMyException", ARCHIVE_CLASSES);
OutputAnalyzer dumpOutput = TestCommon.dump(
appJar, ARCHIVE_CLASSES,
"-Xlog:verification",
"-XX:SharedArchiveConfigFile=" + TestCommon.getSourceFile("DumpTimeVerifyFailure.config.txt"));
TestCommon.checkDump(dumpOutput, "Loading classes to share");
}
}

View File

@ -0,0 +1,3 @@
VERSION: 1.0
@SECTION: String
25: GCStressApp_shared_string

View File

@ -0,0 +1,93 @@
/*
* Copyright (c) 2017, 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.
*
*/
import java.io.*;
import java.util.*;
import sun.hotspot.WhiteBox;
// All strings in archived classes are shared
public class GCStressApp {
static WhiteBox wb = WhiteBox.getWhiteBox();
static int[] arr;
static String get_shared_string() {
String shared_str = "GCStressApp_shared_string";
return shared_str;
}
static String get_shared_string1() {
String shared_str1 = "GCStressApp_shared_string1";
return shared_str1;
}
static void allocAlot() {
try {
Random random = new Random();
for (int i = 0; i < 1024 * 1024; i++) {
int len = random.nextInt(10000);
arr = new int[len];
}
} catch (java.lang.OutOfMemoryError e) { }
}
static void runGC() {
wb.fullGC();
}
public static void main(String args[]) throws Exception {
if (!wb.isSharedClass(GCStressApp.class)) {
System.out.println("GCStressApp is not shared. Possibly there was a mapping failure.");
return;
}
if (wb.areSharedStringsIgnored()) {
System.out.println("Shared strings are ignored.");
return;
}
Object refs = wb.getResolvedReferences(GCStressApp.class);
if (wb.isShared(refs)) {
String shared_str = get_shared_string();
String shared_str1 = get_shared_string1();
if (!wb.isShared(shared_str)) {
throw new RuntimeException("FAILED. GCStressApp_shared_string is not shared");
}
if (!wb.isShared(shared_str1)) {
throw new RuntimeException("FAILED. GCStressApp_shared_string1 is not shared");
}
allocAlot();
runGC();
runGC();
runGC();
System.out.println("Passed");
} else {
System.out.println(
"No cached resolved references. Open archive heap data is not used.");
}
}
}

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2017, 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
* @summary
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @requires (sun.arch.data.model != "32") & (os.family != "windows")
* @requires (vm.gc=="null")
* @library /test/lib /test/hotspot/jtreg/runtime/appcds
* @modules java.base/jdk.internal.misc
* @modules java.management
* jdk.jartool/sun.tools.jar
* @build sun.hotspot.WhiteBox
* @compile GCStressApp.java
* @run main ClassFileInstaller -jar gcstress.jar GCStressApp
* @run main ClassFileInstaller -jar WhiteBox.jar sun.hotspot.WhiteBox
* @run main GCStressTest
*/
import jdk.test.lib.process.OutputAnalyzer;
public class GCStressTest {
public static void main(String[] args) throws Exception {
String wbJar = ClassFileInstaller.getJarPath("WhiteBox.jar");
String use_whitebox_jar = "-Xbootclasspath/a:" + wbJar;
String appJar = ClassFileInstaller.getJarPath("gcstress.jar");
String appClasses[] = TestCommon.list("GCStressApp");
OutputAnalyzer output = TestCommon.dump(appJar, appClasses,
use_whitebox_jar,
"-Xms20M", "-Xmx20M");
output = TestCommon.exec(appJar, use_whitebox_jar,
"-Xlog:cds=info",
"-Xms20M", "-Xmx20M",
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+WhiteBoxAPI","GCStressApp");
TestCommon.checkExec(output);
}
}

View File

@ -0,0 +1,5 @@
Manifest-Version: 1.0
Premain-Class: InstrumentationRegisterClassFileTransformer
Agent-Class: InstrumentationRegisterClassFileTransformer
Can-Retransform-Classes: true
Can-Redefine-Classes: true

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 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
@ -21,11 +21,8 @@
* questions.
*
*/
#ifndef SHARE_VM_CLASSFILE_VMSYMBOLS_EXT_HPP
#define SHARE_VM_CLASSFILE_VMSYMBOLS_EXT_HPP
#define VM_SYMBOLS_DO_EXT(template, do_alias)
#endif // SHARE_VM_CLASSFILE_VMSYMBOLS_EXT_HPP
public class MyException extends Exception {
public MyException(String msg) {
super(msg);
}
}

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2017, 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 class MyOuter {
public void exp() throws MyException {
throw new MyException("MyOuter exception");
}
public void test() throws Exception {
System.out.println("MyOuter");
try {
exp();
} catch (MyException e) {
}
}
public static final class MyInner extends MyOuter {
static String myString = "shared_string_from_MyInner";
public void test() {
System.out.println("MyInner");
}
}
}

View File

@ -0,0 +1,63 @@
/*
* Copyright (c) 2017, 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
* @summary Test open archive heap regions
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @requires (sun.arch.data.model != "32") & (os.family != "windows")
* @requires (vm.gc=="null")
* @library /test/lib /test/hotspot/jtreg/runtime/appcds
* @modules java.base/jdk.internal.misc
* @modules java.management
* jdk.jartool/sun.tools.jar
* @compile ../test-classes/Hello.java
* @run main OpenArchiveRegion
*/
import jdk.test.lib.process.OutputAnalyzer;
public class OpenArchiveRegion {
public static void main(String[] args) throws Exception {
JarBuilder.getOrCreateHelloJar();
String appJar = TestCommon.getTestJar("hello.jar");
String appClasses[] = TestCommon.list("Hello");
// Dump with open archive heap region, requires G1 GC
OutputAnalyzer output = TestCommon.dump(appJar, appClasses);
TestCommon.checkDump(output, "oa0 space:");
output.shouldNotContain("oa0 space: 0 [");
output = TestCommon.exec(appJar, "Hello");
TestCommon.checkExec(output, "Hello World");
output = TestCommon.exec(appJar, "-XX:+UseSerialGC", "Hello");
TestCommon.checkExec(output, "Hello World");
// Dump with open archive heap region disabled when G1 GC is not in use
output = TestCommon.dump(appJar, appClasses, "-XX:+UseParallelGC");
TestCommon.checkDump(output);
output.shouldNotContain("oa0 space:");
output = TestCommon.exec(appJar, "Hello");
TestCommon.checkExec(output, "Hello World");
}
}

View File

@ -0,0 +1,72 @@
/*
* Copyright (c) 2017, 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
* @summary Shared classes can still be used when archived heap regions cannot be
* mapped due to out of range, and -Xshare:on should not fail. Test on
* linux 64-bit only since the HeapBaseMinAddress value is platform specific.
* The value used in the test may cause different behavior on other platforms.
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @requires (os.family == "linux") & (os.arch == "amd64") & (sun.arch.data.model == "64")
* @requires (vm.gc=="null")
* @library /test/lib /test/hotspot/jtreg/runtime/appcds
* @modules java.base/jdk.internal.misc
* @modules java.management
* jdk.jartool/sun.tools.jar
* @compile ../test-classes/Hello.java
* @run main RangeNotWithinHeap
*/
import jdk.test.lib.process.OutputAnalyzer;
public class RangeNotWithinHeap {
public static void main(String[] args) throws Exception {
JarBuilder.getOrCreateHelloJar();
String appJar = TestCommon.getTestJar("hello.jar");
String appClasses[] = TestCommon.list("Hello");
OutputAnalyzer output = TestCommon.dump(appJar, appClasses,
"-XX:HeapBaseMinAddress=0x600000000", "-Xmx6G", "-Xlog:gc+heap=trace");
TestCommon.checkDump(output, "oa0 space:");
// Force archive region out of runtime java heap
output = TestCommon.exec(appJar, "Hello");
TestCommon.checkExec(output, "Hello World");
output = TestCommon.exec(appJar,
"-XX:HeapBaseMinAddress=0x600000000", "-Xmx2G", "-Xlog:gc+heap=trace,cds", "Hello");
TestCommon.checkExec(output, "Hello World");
try {
output.shouldContain(
"UseSharedSpaces: Unable to allocate region, range is not within java heap.");
} catch (Exception e) {
// In rare case the heap data is not used.
if (output.getOutput().contains("Cached heap data from the CDS archive is being ignored")) {
return;
}
// Check for common shared class data mapping failures.
TestCommon.checkCommonExecExceptions(output, e);
}
}
}

View File

@ -0,0 +1,149 @@
/*
* Copyright (c) 2017, 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.
*
*/
import java.lang.instrument.ClassDefinition;
import java.lang.instrument.Instrumentation;
import java.lang.instrument.UnmodifiableClassException;
import java.net.URL;
import java.net.URLClassLoader;
import java.io.File;
import java.security.CodeSigner;
import java.security.CodeSource;
import java.security.ProtectionDomain;
import sun.hotspot.WhiteBox;
public class RedefineClassApp {
static WhiteBox wb = WhiteBox.getWhiteBox();
public static interface Intf { // Loaded from Boot class loader (-Xbootclasspath/a).
public String get();
}
public static class Bar implements Intf { // Loaded from Boot class loader.
public String get() {
return "buzz";
}
}
public static class Foo implements Intf { // Loaded from AppClassLoader
public String get() {
return "buzz";
}
}
static int numTests = 0;
static int failed = 0;
static Instrumentation instrumentation;
public static void main(String args[]) throws Throwable {
if (wb.areSharedStringsIgnored()) {
System.out.println("Shared strings are ignored.");
return;
}
File bootJar = new File(args[0]);
File appJar = new File(args[1]);
instrumentation = InstrumentationRegisterClassFileTransformer.getInstrumentation();
System.out.println("INFO: instrumentation = " + instrumentation);
testBootstrapCDS("Bootstrap Loader", bootJar);
testAppCDSv1("Application Loader", appJar);
if (failed > 0) {
throw new RuntimeException("FINAL RESULT: " + failed + " out of " + numTests + " test case(s) have failed");
} else {
System.out.println("FINAL RESULT: All " + numTests + " test case(s) have passed!");
}
// Full GC. The cached objects in adjustable archive heap regions are
// scanned. The archive regions are verified. No error should be
// reported.
wb.fullGC();
}
static void testBootstrapCDS(String group, File jar) throws Throwable {
doTest(group, new Bar(), jar);
}
static void testAppCDSv1(String group, File jar) throws Throwable {
doTest(group, new Foo(), jar);
}
static void doTest(String group, Intf object, File jar) throws Throwable {
numTests ++;
Class klass = object.getClass();
System.out.println();
System.out.println("++++++++++++++++++++++++++");
System.out.println("Test group: " + group);
System.out.println("Testing with classloader = " + klass.getClassLoader());
System.out.println("Testing with class = " + klass);
System.out.println("Test is shared = " + wb.isSharedClass(klass));
System.out.println("++++++++++++++++++++++++++");
// Call get() before redefine. All strings in archived classes are shared.
String res = object.get();
System.out.println("get() returns " + res);
if (res.equals("buzz") && wb.isShared(res)) {
System.out.println("get() returns " + res + ", string is shared");
} else {
if (!res.equals("buzz")) {
System.out.println("FAILED. buzz is expected but got " + res);
} else {
System.out.println("FAILED. " + res + " is not shared");
}
failed ++;
return;
}
res = null; // release the local reference to the string
// Run GC
System.gc();
System.gc();
System.gc();
// Redefine the shared class
byte[] buff = Util.getClassFileFromJar(jar, klass.getName());
Util.replace(buff, "buzz", "huzz");
String f = "(failed)";
try {
instrumentation.redefineClasses(new ClassDefinition(klass, buff));
f = object.get();
} catch (UnmodifiableClassException|UnsupportedOperationException e) {
e.printStackTrace();
}
if (f.equals("huzz")) {
System.out.println("PASSED: object.get() after redefinition returns " + f);
} else {
System.out.println("FAILED: object.get() after redefinition returns " + f);
failed ++;
}
// Run GC. Should not crash.
System.gc();
System.gc();
System.gc();
System.out.println("++++++++++++++++++++++++++++++++++++++++++++++++ (done)\n\n");
}
}

View File

@ -0,0 +1,105 @@
/*
* Copyright (c) 2017, 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
* @summary Redefine shared class. GC should not cause crash with cached resolved_references.
* @library /test/lib /test/hotspot/jtreg/runtime/appcds /test/hotspot/jtreg/runtime/appcds/test-classes /test/hotspot/jtreg/runtime/appcds/jvmti
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @requires vm.gc.G1
* @requires vm.flavor != "minimal"
* @requires (sun.arch.data.model != "32") & (os.family != "windows")
* @modules java.base/jdk.internal.misc
* jdk.jartool/sun.tools.jar
* java.management
* @build sun.hotspot.WhiteBox
* RedefineClassApp
* InstrumentationClassFileTransformer
* InstrumentationRegisterClassFileTransformer
* @run main/othervm RedefineClassTest
*/
import com.sun.tools.attach.VirtualMachine;
import com.sun.tools.attach.VirtualMachineDescriptor;
import java.io.File;
import java.io.FileOutputStream;
import java.util.List;
import jdk.test.lib.Asserts;
import jdk.test.lib.cds.CDSOptions;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
public class RedefineClassTest {
public static String bootClasses[] = {
"RedefineClassApp$Intf",
"RedefineClassApp$Bar",
"sun.hotspot.WhiteBox",
};
public static String appClasses[] = {
"RedefineClassApp",
"RedefineClassApp$Foo",
};
public static String sharedClasses[] = TestCommon.concat(bootClasses, appClasses);
public static String agentClasses[] = {
"InstrumentationClassFileTransformer",
"InstrumentationRegisterClassFileTransformer",
"Util",
};
public static void main(String[] args) throws Throwable {
runTest();
}
public static void runTest() throws Throwable {
String bootJar =
ClassFileInstaller.writeJar("RedefineClassBoot.jar", bootClasses);
String appJar =
ClassFileInstaller.writeJar("RedefineClassApp.jar", appClasses);
String agentJar =
ClassFileInstaller.writeJar("InstrumentationAgent.jar",
ClassFileInstaller.Manifest.fromSourceFile("InstrumentationAgent.mf"),
agentClasses);
String bootCP = "-Xbootclasspath/a:" + bootJar;
String agentCmdArg;
agentCmdArg = "-javaagent:" + agentJar;
TestCommon.testDump(appJar, sharedClasses, bootCP, "-Xlog:gc+region=trace");
OutputAnalyzer out = TestCommon.execAuto("-cp", appJar,
bootCP,
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+WhiteBoxAPI",
"-Xlog:gc+region=trace,cds=info",
agentCmdArg,
"RedefineClassApp", bootJar, appJar);
out.reportDiagnosticSummary();
CDSOptions opts = (new CDSOptions()).setXShareMode("auto");
TestCommon.checkExec(out, opts);
}
}

View File

@ -0,0 +1,138 @@
/*
* Copyright (c) 2015, 2017, 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
* @summary Tests the format checking of class list format.
*
* (NOTE: AppCDS does not support uncompressed oops)
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @requires (sun.arch.data.model == "64")
* @requires ((os.family == "linux") & (os.arch=="amd64")) | (os.family == "solaris")
* @library /test/lib /test/hotspot/jtreg/runtime/appcds
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @compile test-classes/Hello.java test-classes/CustomLoadee.java test-classes/CustomLoadee2.java
* test-classes/CustomInterface2_ia.java test-classes/CustomInterface2_ib.java
* @run main ClassListFormatA
*/
public class ClassListFormatA extends ClassListFormatBase {
static {
// Uncomment the following line to run only one of the test cases
// ClassListFormatBase.RUN_ONLY_TEST = "TESTCASE A1";
}
public static void main(String[] args) throws Throwable {
String appJar = JarBuilder.getOrCreateHelloJar();
String customJarPath = JarBuilder.build("ClassListFormatA", "CustomLoadee",
"CustomLoadee2", "CustomInterface2_ia", "CustomInterface2_ib");
//----------------------------------------------------------------------
// TESTGROUP A: general bad input
//----------------------------------------------------------------------
dumpShouldFail(
"TESTCASE A1: bad input - interface: instead of interfaces:",
appJar, classlist(
"Hello",
"java/lang/Object id: 1",
"CustomLoadee interface: 1"
),
"Unknown input:");
dumpShouldFail(
"TESTCASE A2: bad input - negative IDs not allowed",
appJar, classlist(
"Hello",
"java/lang/Object id: -1"
),
"Error: negative integers not allowed");
dumpShouldFail(
"TESTCASE A3: bad input - bad ID (not an integer)",
appJar, classlist(
"Hello",
"java/lang/Object id: xyz"
),
"Error: expected integer");
if (false) {
// FIXME - classFileParser.cpp needs fixing.
dumpShouldFail(
"TESTCASE A4: bad input - bad ID (integer too big)",
appJar, classlist(
"Hello",
"java/lang/Object id: 2147483648" // <- this is 0x80000000
),
"Error: expected integer");
// FIXME
dumpShouldFail(
"TESTCASE A5: bad input - bad ID (integer too big)",
appJar, classlist(
"Hello",
"java/lang/Object id: 21474836489" // bigger than 32-bit!
),
"Error: expected integer");
}
// Good input:
dumpShouldPass(
"TESTCASE A6: extraneous spaces, tab characters and trailing new line characters",
appJar, classlist(
"Hello ", // trailing spaces
"java/lang/Object\tid:\t1", // \t instead of ' '
"CustomLoadee id: 2 super: 1 source: " + customJarPath,
"CustomInterface2_ia id: 3 super: 1 source: " + customJarPath + " ",
"CustomInterface2_ib id: 4 super: 1 source: " + customJarPath + "\t\t\r" ,
"CustomLoadee2 id: 5 super: 1 interfaces: 3 4 source: " + customJarPath // preceding spaces
));
int _max_allowed_line = 4096; // Must match ClassListParser::_max_allowed_line in C code.
int _line_buf_extra = 10; // Must match ClassListParser::_line_buf_extra in C code.
StringBuffer sbuf = new StringBuffer();
for (int i=0; i<_max_allowed_line+1; i++) {
sbuf.append("x");
}
dumpShouldFail(
"TESTCASE A7: bad input - line too long",
appJar, classlist(
sbuf.toString()
),
"input line too long (must be no longer than " + _max_allowed_line + " chars");
for (int i=0; i<_line_buf_extra + 1000; i++) {
sbuf.append("X");
}
dumpShouldFail(
"TESTCASE A8: bad input - line too long: try to overflow C buffer",
appJar, classlist(
sbuf.toString()
),
"input line too long (must be no longer than " + _max_allowed_line + " chars");
}
}

View File

@ -0,0 +1,74 @@
/*
* Copyright (c) 2015, 2017, 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
* @summary Tests the format checking of hotspot/src/closed/share/vm/classfile/classListParser.cpp.
*
* (NOTE: AppCDS does not support uncompressed oops)
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @requires (sun.arch.data.model == "64")
* @requires ((os.family == "linux") & (os.arch=="amd64")) | (os.family == "solaris")
* @library /test/lib /test/hotspot/jtreg/runtime/appcds
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @compile test-classes/Hello.java test-classes/CustomLoadee.java test-classes/CustomLoadee2.java
* test-classes/CustomInterface2_ia.java test-classes/CustomInterface2_ib.java
* @run main ClassListFormatB
*/
public class ClassListFormatB extends ClassListFormatBase {
static {
// Uncomment the following line to run only one of the test cases
// ClassListFormatBase.RUN_ONLY_TEST = "TESTCASE B1";
}
public static void main(String[] args) throws Throwable {
String appJar = JarBuilder.getOrCreateHelloJar();
String customJarPath = JarBuilder.build("ClassListFormatB", "CustomLoadee",
"CustomLoadee2", "CustomInterface2_ia", "CustomInterface2_ib");
//----------------------------------------------------------------------
// TESTGROUP B if source IS specified
//----------------------------------------------------------------------
dumpShouldFail(
"TESTCASE B1: if source: is specified, must specify super:",
appJar, classlist(
"Hello",
"java/lang/Object id: 1",
"CustomLoadee id: 2 source: " + customJarPath
),
"If source location is specified, super class must be also specified");
dumpShouldFail(
"TESTCASE B2: if source: is specified, must specify id:",
appJar, classlist(
"Hello",
"java/lang/Object id: 1",
"CustomLoadee super: 1 source: " + customJarPath
),
"If source location is specified, id must be also specified");
}
}

View File

@ -0,0 +1,82 @@
/*
* Copyright (c) 2015, 2017, 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.
*
*/
import jdk.test.lib.process.OutputAnalyzer;
/**
* Base class for ClassListFormat[A,B,C...].java
*/
public class ClassListFormatBase {
protected static String RUN_ONLY_TEST = null;
static void dumpShouldFail(String caseHelp, String appJar, String[] appClasses,
String... expected_errors) throws Throwable {
if (RUN_ONLY_TEST != null && !caseHelp.startsWith(RUN_ONLY_TEST)) {
System.out.println("Skipped via RUN_ONLY_TEST: " + caseHelp);
return;
}
System.out.println("------------------------------");
System.out.println(caseHelp);
System.out.println("------------------------------");
try {
OutputAnalyzer output = TestCommon.dump(appJar, appClasses);
output.shouldHaveExitValue(1);
for (String s : expected_errors) {
output.shouldContain(s);
}
} catch (Throwable t) {
System.out.println("FAILED CASE: " + caseHelp);
throw t;
}
}
static void dumpShouldPass(String caseHelp, String appJar, String[] appClasses,
String... expected_msgs) throws Throwable {
if (RUN_ONLY_TEST != null && !caseHelp.startsWith(RUN_ONLY_TEST)) {
System.out.println("Skipped via RUN_ONLY_TEST: " + caseHelp);
return;
}
System.out.println("------------------------------");
System.out.println(caseHelp);
System.out.println("------------------------------");
try {
OutputAnalyzer output = TestCommon.dump(appJar, appClasses);
output.shouldHaveExitValue(0);
output.shouldContain("Dumping");
for (String s : expected_msgs) {
output.shouldContain(s);
}
} catch (Throwable t) {
System.out.println("FAILED CASE: " + caseHelp);
throw t;
}
}
static String[] classlist(String... args) {
return TestCommon.list(args);
}
}

View File

@ -0,0 +1,76 @@
/*
* Copyright (c) 2015, 2017, 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
* @summary Tests the format checking of hotspot/src/closed/share/vm/classfile/classListParser.cpp.
*
* (NOTE: AppCDS does not support uncompressed oops)
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @requires (sun.arch.data.model == "64")
* @requires ((os.family == "linux") & (os.arch=="amd64")) | (os.family == "solaris")
* @library /test/lib /test/hotspot/jtreg/runtime/appcds
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @compile test-classes/Hello.java test-classes/CustomLoadee.java test-classes/CustomLoadee2.java
* test-classes/CustomInterface2_ia.java test-classes/CustomInterface2_ib.java
* @run main ClassListFormatC
*/
public class ClassListFormatC extends ClassListFormatBase {
static {
// Uncomment the following line to run only one of the test cases
// ClassListFormatBase.RUN_ONLY_TEST = "TESTCASE C1";
}
public static void main(String[] args) throws Throwable {
String appJar = JarBuilder.getOrCreateHelloJar();
String customJarPath = JarBuilder.build("ClassListFormatC", "CustomLoadee",
"CustomLoadee2", "CustomInterface2_ia",
"CustomInterface2_ib");
//----------------------------------------------------------------------
// TESTGROUP C: if source IS NOT specified
//----------------------------------------------------------------------
dumpShouldFail(
"TESTCASE C1: if source: is NOT specified, must NOT specify super:",
appJar, classlist(
"Hello",
"java/lang/Object id: 1",
"CustomLoadee super: 1"
),
"If source location is not specified, super class must not be specified");
dumpShouldFail(
"TESTCASE C2: if source: is NOT specified, must NOT specify interface:",
appJar, classlist(
"Hello",
"java/lang/Object id: 1",
"CustomLoadee interfaces: 1"
),
"If source location is not specified, interface(s) must not be specified");
}
}

View File

@ -0,0 +1,85 @@
/*
* Copyright (c) 2015, 2017, 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
* @summary Tests the format checking of hotspot/src/closed/share/vm/classfile/classListParser.cpp.
*
* (NOTE: AppCDS does not support uncompressed oops)
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @requires (sun.arch.data.model == "64")
* @requires ((os.family == "linux") & (os.arch=="amd64")) | (os.family == "solaris")
* @library /test/lib /test/hotspot/jtreg/runtime/appcds
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @compile test-classes/Hello.java test-classes/CustomLoadee.java test-classes/CustomLoadee2.java
* test-classes/CustomInterface2_ia.java test-classes/CustomInterface2_ib.java
* @run main ClassListFormatD
*/
public class ClassListFormatD extends ClassListFormatBase {
static {
// Uncomment the following line to run only one of the test cases
// ClassListFormatBase.RUN_ONLY_TEST = "TESTCASE D1";
}
public static void main(String[] args) throws Throwable {
String appJar = JarBuilder.getOrCreateHelloJar();
String customJarPath = JarBuilder.build("ClassListFormatD", "CustomLoadee",
"CustomLoadee2", "CustomInterface2_ia",
"CustomInterface2_ib");
//----------------------------------------------------------------------
// TESTGROUP D: bad use of IDs
//----------------------------------------------------------------------
dumpShouldFail(
"TESTCASE D1: duplicated id:",
appJar, classlist(
"Hello",
"java/lang/Object id: 1",
"CustomLoadee id: 1 super: 1 source: " + customJarPath
),
"Duplicated ID 1 for class CustomLoadee");
dumpShouldFail(
"TESTCASE D2: bad ID for super:",
appJar, classlist(
"Hello",
"java/lang/Object id: 1",
"CustomLoadee id: 2 super: 2 source: " + customJarPath
),
"Super class id 2 is not yet loaded");
dumpShouldFail(
"TESTCASE D3: bad ID in interfaces:",
appJar, classlist(
"Hello",
"java/lang/Object id: 1",
"CustomLoadee id: 2 super: 1 interfaces: 2 source: " + customJarPath
),
"Interface id 2 is not yet loaded");
}
}

View File

@ -0,0 +1,111 @@
/*
* Copyright (c) 2015, 2017, 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
* @summary Tests the format checking of hotspot/src/closed/share/vm/classfile/classListParser.cpp.
*
* (NOTE: AppCDS does not support uncompressed oops)
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @requires (sun.arch.data.model == "64")
* @requires ((os.family == "linux") & (os.arch=="amd64")) | (os.family == "solaris")
* @library /test/lib /test/hotspot/jtreg/runtime/appcds
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @compile test-classes/Hello.java test-classes/CustomLoadee.java test-classes/CustomLoadee2.java
* test-classes/CustomInterface2_ia.java test-classes/CustomInterface2_ib.java
* @run main ClassListFormatE
*/
public class ClassListFormatE extends ClassListFormatBase {
static {
// Uncomment the following line to run only one of the test cases
// ClassListFormatBase.RUN_ONLY_TEST = "TESTCASE E1";
}
public static void main(String[] args) throws Throwable {
String appJar = JarBuilder.getOrCreateHelloJar();
String customJarPath = JarBuilder.build("ClassListFormatE", "CustomLoadee",
"CustomLoadee2", "CustomInterface2_ia",
"CustomInterface2_ib");
//----------------------------------------------------------------------
// TESTGROUP E: super class and interfaces
//----------------------------------------------------------------------
dumpShouldFail(
"TESTCASE E1: missing interfaces: keyword",
appJar, classlist(
"Hello",
"java/lang/Object id: 1",
"CustomLoadee2 id: 1 super: 1 source: " + customJarPath
),
"Class CustomLoadee2 implements the interface CustomInterface2_ia, but no interface has been specified in the input line");
dumpShouldFail(
"TESTCASE E2: missing one interface",
appJar, classlist(
"Hello",
"java/lang/Object id: 1",
"CustomInterface2_ia id: 2 super: 1 source: " + customJarPath,
"CustomInterface2_ib id: 3 super: 1 source: " + customJarPath,
"CustomLoadee2 id: 4 super: 1 interfaces: 2 source: " + customJarPath
),
"The interface CustomInterface2_ib implemented by class CustomLoadee2 does not match any of the specified interface IDs");
dumpShouldFail(
"TESTCASE E3: specifying an interface that's not implemented by the class",
appJar, classlist(
"Hello",
"java/lang/Object id: 1",
"CustomInterface2_ia id: 2 super: 1 source: " + customJarPath,
"CustomLoadee id: 2 super: 1 interfaces: 2 source: " + customJarPath
),
"The number of interfaces (1) specified in class list does not match the class file (0)");
dumpShouldFail(
"TESTCASE E4: repeating an ID in the interfaces: keyword",
appJar, classlist(
"Hello",
"java/lang/Object id: 1",
"CustomInterface2_ia id: 2 super: 1 source: " + customJarPath,
"CustomInterface2_ib id: 3 super: 1 source: " + customJarPath,
"CustomLoadee2 id: 4 super: 1 interfaces: 2 2 3 source: " + customJarPath
),
"The number of interfaces (3) specified in class list does not match the class file (2)");
dumpShouldFail(
"TESTCASE E5: wrong super class",
appJar, classlist(
"Hello",
"java/lang/Object id: 1",
"CustomInterface2_ia id: 2 super: 1 source: " + customJarPath,
"CustomInterface2_ib id: 3 super: 1 source: " + customJarPath,
"CustomLoadee id: 4 super: 1 source: " + customJarPath,
"CustomLoadee2 id: 5 super: 4 interfaces: 2 3 source: " + customJarPath
),
"The specified super class CustomLoadee (id 4) does not match actual super class java.lang.Object");
}
}

View File

@ -0,0 +1,110 @@
/*
* Copyright (c) 2016, 2017, 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.
*
*/
// This is a utlitity test class for loading classes-under-test
// by means of custom class loader.
// See AppCDS/jvmti/transformRelatedClasses/TransformRelatedClasses.java
// for an example.
// Use this test app in conjunction with other tests
// to load and exercise classes using custom class loader(s).
// This class is intended to be called by the "main test driver"
// inside a child process, normally with sharing enabled.
//
// Arguments: customJarPath, loaderType, testClass
// customJarPath - a path to jar file containing classes for
// loading via this custom class loader, including the
// testClass
// loaderType - Currently only "unregistered"
// (Fingerprint verification method) is allowed
// testClass - the class to be loader; the test method with
// signature 'public static void test()' will be called
// on this class, so class must contain such method
import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.logging.Logger;
public class CustomLoaderApp {
public static void ping() {};
private static void log(String msg) {
System.out.println("CustomLoaderApp: " + msg);
}
public static void main(String[] args) throws Exception {
String path = args[0];
URL url = new File(path).toURI().toURL();
URL[] urls = new URL[] {url};
String loaderType = args[1];
log("loaderType = " + loaderType);
String testClass = args[2];
log("testClass = " + testClass);
switch(loaderType) {
case "unregistered":
loadAndUseWithUnregisteredLoader(urls, testClass);
break;
default:
throw new IllegalArgumentException("loader type is wrong: " + loaderType);
}
}
// Load the test classes using unregistered loader
// (i.e. loader that is not using AppCDS API)
private static void loadAndUseWithUnregisteredLoader(URL[] urls, String testClass)
throws Exception {
URLClassLoader urlClassLoader = new URLClassLoader(urls);
callTestMethod(loadAndCheck(urlClassLoader, testClass));
}
private static Class loadAndCheck(ClassLoader loader, String className)
throws ClassNotFoundException {
Class c = loader.loadClass(className);
log("class =" + c);
log("loader = " + c.getClassLoader());
// Check that c is defined by the correct loader
if (c.getClassLoader() != loader) {
String msg = String.format("c.getClassLoader() equals to <%s>, expected <%s>",
c.getClassLoader(), loader);
throw new RuntimeException(msg);
}
return c;
}
private static void callTestMethod(Class c) throws Exception {
Method[] methods = c.getDeclaredMethods();
for (Method m : methods) {
log("method = " + m.getName());
if (m.getName().equals("test"))
m.invoke(null);
}
}
}

View File

@ -0,0 +1,75 @@
/*
* Copyright (c) 2015, 2017, 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
* @summary Hello World test for AppCDS custom loader support
* (NOTE: AppCDS does not support uncompressed oops)
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @requires (sun.arch.data.model == "64")
* @requires ((os.family == "linux") & (os.arch=="amd64")) | (os.family == "solaris")
* @library /test/lib /test/hotspot/jtreg/runtime/appcds
* @modules java.base/jdk.internal.misc
* java.management
* @compile test-classes/Hello.java test-classes/CustomLoadee.java
* @build sun.hotspot.WhiteBox
* @run main ClassFileInstaller -jar hello.jar Hello
* @run main ClassFileInstaller -jar hello_custom.jar CustomLoadee
* @run main ClassFileInstaller -jar WhiteBox.jar sun.hotspot.WhiteBox
* @run main HelloCustom
*/
import jdk.test.lib.process.OutputAnalyzer;
import sun.hotspot.WhiteBox;
public class HelloCustom {
public static void main(String[] args) throws Exception {
String wbJar = ClassFileInstaller.getJarPath("WhiteBox.jar");
String use_whitebox_jar = "-Xbootclasspath/a:" + wbJar;
String appJar = ClassFileInstaller.getJarPath("hello.jar");
String customJarPath = ClassFileInstaller.getJarPath("hello_custom.jar");
// Dump the archive
String classlist[] = new String[] {
"Hello",
"java/lang/Object id: 1",
"CustomLoadee id: 2 super: 1 source: " + customJarPath
};
OutputAnalyzer output;
TestCommon.testDump(appJar, classlist,
// command-line arguments ...
use_whitebox_jar);
output = TestCommon.exec(appJar,
// command-line arguments ...
use_whitebox_jar,
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+WhiteBoxAPI",
"Hello", customJarPath);
TestCommon.checkExec(output);
}
}

View File

@ -0,0 +1,125 @@
/*
* Copyright (c) 2015, 2017, 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
* @summary Check that during dumping, the classes for BOOT/EXT/APP loaders are segregated from the
* custom loader classes.
* (NOTE: AppCDS does not support uncompressed oops)
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @requires (sun.arch.data.model == "64")
* @requires ((os.family == "linux") & (os.arch=="amd64")) | (os.family == "solaris")
* @library /test/lib /test/hotspot/jtreg/runtime/appcds
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @compile test-classes/LoaderSegregation.java
* test-classes/CustomLoadee.java test-classes/CustomLoadee2.java
* test-classes/CustomInterface2_ia.java test-classes/CustomInterface2_ib.java
* test-classes/CustomLoadee3.java test-classes/CustomLoadee3Child.java
* test-classes/OnlyBuiltin.java
* test-classes/OnlyUnregistered.java
* ../test-classes/Util.java
* @build sun.hotspot.WhiteBox
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* @run main LoaderSegregationTest
*/
import jdk.test.lib.process.OutputAnalyzer;
import sun.hotspot.WhiteBox;
/**
* See "Handling of the classes in the AppCDS archive" at the top of
* systemDicrionatyShared.hpp.
*
* This test ensure that the 2 types of archived classes (BUILTIN and UNREGISTERED)
* are segregated at both dump-time and run time:
*
* [A] An archived BUILTIN class cannot be a subclass of a non-BUILTIN class.
* [B] An archived BUILTIN class cannot implement a non-BUILTIN interface.
* [C] BUILTIN and UNREGISTERED classes can be loaded only by their corresponding
* type of loaders.
*
*/
public class LoaderSegregationTest {
public static void main(String[] args) throws Exception {
String wbJar = JarBuilder.build(true, "WhiteBox", "sun/hotspot/WhiteBox");
String use_whitebox_jar = "-Xbootclasspath/a:" + wbJar;
String appJar = JarBuilder.build("LoaderSegregation_app", "LoaderSegregation",
"CustomLoadee", "CustomLoadee2", "CustomLoadee3Child", "CustomInterface2_ia",
"OnlyBuiltin", "Util");
String app2Jar = JarBuilder.build("LoaderSegregation_app2", "CustomLoadee3", "CustomInterface2_ib");
String customJarPath = JarBuilder.build("LoaderSegregation_custom", "CustomLoadee",
"CustomLoadee2", "CustomInterface2_ia", "CustomInterface2_ib",
"CustomLoadee3", "CustomLoadee3Child",
"OnlyBuiltin", "OnlyUnregistered");
// Dump the archive
String classlist[] = new String[] {
"LoaderSegregation",
"java/lang/Object id: 1",
// These are the UNREGISTERED classes: they have "source:"
// but they don't have "loader:".
"CustomLoadee id: 2 super: 1 source: " + customJarPath,
"CustomInterface2_ia id: 3 super: 1 source: " + customJarPath,
"CustomInterface2_ib id: 4 super: 1 source: " + customJarPath,
"CustomLoadee2 id: 5 super: 1 interfaces: 3 4 source: " + customJarPath,
"CustomLoadee3 id: 6 super: 1 source: " + customJarPath,
"CustomLoadee3Child id: 7 super: 6 source: " + customJarPath,
// At dump time, the following BUILTIN classes are loaded after the UNREGISTERED
// classes from above. However, at dump time, they cannot use the UNREGISTERED classes are their
// super or interface.
"CustomLoadee", // can be loaded at dump time
"CustomLoadee2", // cannot be loaded at dump time (interface missing)
"CustomLoadee3Child", // cannot be loaded at dump time (super missing)
// Check that BUILTIN and UNREGISTERED classes can be loaded only by their
// corresponding type of loaders.
"OnlyBuiltin",
"OnlyUnregistered id: 9 super: 1 source: " + customJarPath,
};
OutputAnalyzer output;
TestCommon.testDump(appJar, classlist,
// command-line arguments ...
use_whitebox_jar);
output = TestCommon.exec(TestCommon.concatPaths(appJar, app2Jar),
// command-line arguments ...
"--add-opens=java.base/java.lang=ALL-UNNAMED",
"--add-opens=java.base/java.security=ALL-UNNAMED",
use_whitebox_jar,
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+WhiteBoxAPI",
"LoaderSegregation", customJarPath);
TestCommon.checkExec(output);
}
}

View File

@ -0,0 +1,99 @@
/*
* Copyright (c) 2015, 2017, 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.
*
*/
import jdk.test.lib.process.OutputAnalyzer;
/*
* This is a base class for the following test cases:
* ParallelTestMultiFP.java
* ParallelTestSingleFP.java
*/
public class ParallelTestBase {
public static final int MAX_CLASSES = 40; // must match ../test-classes/ParallelLoad.java
public static int NUM_THREADS = 4; // must match ../test-classes/ParallelLoad.java
public static final int SINGLE_CUSTOM_LOADER = 1;
public static final int MULTI_CUSTOM_LOADER = 2;
public static final int FINGERPRINT_MODE = 1;
public static void run(String[] args, int loaderType, int mode) throws Exception {
String[] cust_classes = new String[MAX_CLASSES];
String[] cust_list;
if (mode == FINGERPRINT_MODE) {
cust_list = new String[MAX_CLASSES];
} else {
cust_list = new String[MAX_CLASSES * NUM_THREADS];
}
for (int i = 0; i<MAX_CLASSES; i++) {
cust_classes[i] = "ParallelClass" + i;
}
String customJarPath = JarBuilder.build("ParallelTestBase", cust_classes);
for (int i = 0, n=0; i<MAX_CLASSES; i++) {
int super_id = 1;
if (mode == FINGERPRINT_MODE) {
// fingerprint mode -- no need to use the "loader:" option.
int id = i + 2;
cust_list[i] = cust_classes[i] + " id: " + id + " super: " + super_id + " source: " + customJarPath;
} else {
throw new RuntimeException("Only FINGERPRINT_MODE is supported");
}
}
String app_list[];
String mainClass;
String appJar;
if (mode == FINGERPRINT_MODE) {
appJar = JarBuilder.build("parallel_fp",
"ParallelLoad",
"ParallelLoadThread",
"ParallelLoadWatchdog");
app_list = new String[] {
"java/lang/Object id: 1",
"ParallelLoad",
"ParallelLoadThread",
"ParallelLoadWatchdog"
};
mainClass = "ParallelLoad";
} else {
throw new RuntimeException("Currently only FINGERPRINT_MODE is supported");
}
OutputAnalyzer output;
TestCommon.testDump(appJar, TestCommon.concat(app_list, cust_list));
String loaderTypeArg = (loaderType == SINGLE_CUSTOM_LOADER) ? "SINGLE_CUSTOM_LOADER" : "MULTI_CUSTOM_LOADER";
String modeArg = "FINGERPRINT_MODE";
output = TestCommon.exec(appJar,
// command-line arguments ...
"--add-opens=java.base/java.security=ALL-UNNAMED",
mainClass, loaderTypeArg, modeArg, customJarPath);
TestCommon.checkExec(output);
}
}

View File

@ -0,0 +1,44 @@
/*
* Copyright (c) 2015, 2017, 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
* @summary Load classes from CDS archive into multiple custom loader using parallel threads
* (NOTE: AppCDS does not support uncompressed oops)
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @requires (sun.arch.data.model == "64")
* @requires ((os.family == "linux") & (os.arch=="amd64")) | (os.family == "solaris")
* @library /test/lib /test/hotspot/jtreg/runtime/appcds
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @compile ../test-classes/ParallelLoad.java ../test-classes/ParallelClasses.java
* @run main ParallelTestMultiFP
*/
public class ParallelTestMultiFP extends ParallelTestBase {
public static void main(String[] args) throws Exception {
ParallelTestBase.run(args, MULTI_CUSTOM_LOADER, FINGERPRINT_MODE);
}
}

View File

@ -0,0 +1,44 @@
/*
* Copyright (c) 2015, 2017, 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
* @summary Load classes from CDS archive into a single custom loader using parallel threads (finger print)
* (NOTE: AppCDS does not support uncompressed oops)
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @requires (sun.arch.data.model == "64")
* @requires ((os.family == "linux") & (os.arch=="amd64")) | (os.family == "solaris")
* @library /test/lib /test/hotspot/jtreg/runtime/appcds
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @compile ../test-classes/ParallelLoad.java ../test-classes/ParallelClasses.java
* @run main ParallelTestSingleFP
*/
public class ParallelTestSingleFP extends ParallelTestBase {
public static void main(String[] args) throws Exception {
ParallelTestBase.run(args, SINGLE_CUSTOM_LOADER, FINGERPRINT_MODE);
}
}

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2015, 2017, 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
* @summary Make sure prohibited packages cannot be stored into archive for custom loaders.
* (NOTE: AppCDS does not support uncompressed oops)
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @requires (sun.arch.data.model == "64")
* @requires ((os.family == "linux") & (os.arch=="amd64")) | (os.family == "solaris")
* @library /test/lib /test/hotspot/jtreg/runtime/appcds
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @compile ClassListFormatBase.java test-classes/Hello.java test-classes/InProhibitedPkg.java
* @run main ProhibitedPackageNamesTest
*/
public class ProhibitedPackageNamesTest extends ClassListFormatBase {
static {
// Uncomment the following line to run only one of the test cases
// ClassListFormatBase.RUN_ONLY_TEST = "TESTCASE PPN1";
}
public static void main(String[] args) throws Throwable {
String appJar = JarBuilder.getOrCreateHelloJar();
String customJarPath = JarBuilder.build("ProhibitedPackageNames_custom", "java/InProhibitedPkg");
dumpShouldPass(
"TESTCASE PPN1: prohibited package name without loader:",
appJar, classlist(
"Hello",
"java/lang/Object id: 1",
// Without "loader:" keyword.
"java/InProhibitedPkg id: 2 super: 1 source: " + customJarPath
),
"Prohibited package for non-bootstrap classes: java/InProhibitedPkg.class");
}
}

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2016, 2017, 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
* @summary AppCDS handling of protection domain in custom loaders.
*
* AppCDS does not support uncompressed oops
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @requires (sun.arch.data.model == "64")
* @requires ((os.family == "linux") & (os.arch=="amd64")) | (os.family == "solaris")
*
* @library /test/lib /test/hotspot/jtreg/runtime/appcds
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @compile test-classes/ProtDomain.java
* @run main ProtectionDomain
*/
public class ProtectionDomain {
public static void main(String[] args) throws Exception {
String appJar = JarBuilder.build("ProtectionDomain-app", "ProtDomain");
String customJar = JarBuilder.build("ProtectionDomain-custom",
"ProtDomainClassForArchive", "ProtDomainNotForArchive");
String[] classlist = new String[] {
"java/lang/Object id: 1",
"ProtDomain id: 2 super: 1 source: " + appJar,
"ProtDomainClassForArchive id: 3 super: 1 source: " + customJar
};
TestCommon.testDump(appJar, classlist);
// First class is loaded from CDS, second class is loaded from JAR
TestCommon.checkExec(TestCommon.exec(appJar, "-verbose:class", "ProtDomain", customJar),
"[class,load] ProtDomainClassForArchive source: shared objects file",
"[class,load] ProtDomainNotForArchive source: file");
}
}

View File

@ -0,0 +1,94 @@
/*
* Copyright (c) 2015, 2017, 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
* @summary Testing the loading of a class with the same name in two different class loaders.
*
* (NOTE: AppCDS does not support uncompressed oops)
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @requires (sun.arch.data.model == "64")
* @requires ((os.family == "linux") & (os.arch=="amd64")) | (os.family == "solaris")
*
* @library /test/lib /test/hotspot/jtreg/runtime/appcds
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @compile test-classes/CustomLoadee.java
* test-classes/CustomLoadee3.java
* test-classes/SameNameUnrelatedLoaders.java
* @build sun.hotspot.WhiteBox
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* @run main SameNameInTwoLoadersTest
*/
import jdk.test.lib.process.OutputAnalyzer;
import sun.hotspot.WhiteBox;
public class SameNameInTwoLoadersTest {
private static String appJar;
private static String customJar;
private static String useWbParam;
public static void main(String[] args) throws Exception {
appJar = JarBuilder.build("SameNameInTwoLoadersTest",
"SameNameUnrelatedLoaders");
customJar = JarBuilder.build("SameNameInTwoLoadersTest_custom", "CustomLoadee", "CustomLoadee3");
useWbParam = "-Xbootclasspath/a:" +
JarBuilder.build(true, "WhiteBox", "sun/hotspot/WhiteBox");;
// ====== unrelated loaders
executeTestCase(getClassList_FP(),
"SameNameUnrelatedLoaders", "FpBoth");
}
private static void executeTestCase(String[] classlist,
String testClass, String testCaseId) throws Exception {
classlist[0] = testClass;
TestCommon.testDump(appJar, classlist, useWbParam);
OutputAnalyzer output = TestCommon.exec(appJar,
// command-line arguments ...
"--add-opens=java.base/java.security=ALL-UNNAMED",
useWbParam,
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+WhiteBoxAPI",
testClass,
customJar, testCaseId);
TestCommon.checkExec(output);
}
// Single entry, no loader specified (FP method)
private static String[] getClassList_FP() {
return new String[] {
"SameNameUnrelatedLoaders",
"java/lang/Object id: 1",
"CustomLoadee id: 10 super: 1 source: " + customJar,
};
}
}

View File

@ -0,0 +1,76 @@
/*
* Copyright (c) 2015, 2017, 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
* @summary Make sure classes intended for custom loaders cannot be loaded by BOOT/EXT/APP loaders
* (NOTE: AppCDS does not support uncompressed oops)
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
* @requires (sun.arch.data.model == "64")
* @requires ((os.family == "linux") & (os.arch=="amd64")) | (os.family == "solaris")
* @library /test/lib /test/hotspot/jtreg/runtime/appcds
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @compile test-classes/UnintendedLoaders.java test-classes/CustomLoadee.java
* @build sun.hotspot.WhiteBox
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* @run main UnintendedLoadersTest
*/
import jdk.test.lib.process.OutputAnalyzer;
import sun.hotspot.WhiteBox;
public class UnintendedLoadersTest {
public static void main(String[] args) throws Exception {
String wbJar = JarBuilder.build(true, "WhiteBox", "sun/hotspot/WhiteBox");
String use_whitebox_jar = "-Xbootclasspath/a:" + wbJar;
String appJar = JarBuilder.build("UnintendedLoaders_app", "UnintendedLoaders");
String customJarPath = JarBuilder.build("UnintendedLoaders_custom", "CustomLoadee");
// Dump the archive
String classlist[] = new String[] {
"UnintendedLoadersTest",
"java/lang/Object id: 1",
// Without "loader:" keyword.
"CustomLoadee id: 2 super: 1 source: " + customJarPath,
};
OutputAnalyzer output;
TestCommon.testDump(appJar, classlist,
// command-line arguments ...
use_whitebox_jar);
output = TestCommon.exec(appJar,
// command-line arguments ...
use_whitebox_jar,
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+WhiteBoxAPI",
"UnintendedLoaders");
TestCommon.checkExec(output);
}
}

Some files were not shown because too many files have changed in this diff Show More