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:
parent
570a828dfc
commit
61e736cbae
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
248
src/hotspot/share/classfile/sharedClassUtil.cpp
Normal file
248
src/hotspot/share/classfile/sharedClassUtil.cpp
Normal 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;
|
||||
}
|
@ -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
|
||||
|
@ -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());
|
||||
|
1086
src/hotspot/share/classfile/systemDictionaryShared.cpp
Normal file
1086
src/hotspot/share/classfile/systemDictionaryShared.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -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) {}
|
||||
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) {
|
||||
return NULL;
|
||||
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);
|
||||
}
|
||||
static void roots_oops_do(OopClosure* blk) {}
|
||||
static void oops_do(OopClosure* 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);
|
||||
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,
|
||||
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;
|
||||
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
|
||||
|
@ -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
|
||||
|
@ -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*/
|
||||
|
||||
|
69
src/hotspot/share/prims/cdsoffsets.cpp
Normal file
69
src/hotspot/share/prims/cdsoffsets.cpp
Normal 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
|
48
src/hotspot/share/prims/cdsoffsets.hpp
Normal file
48
src/hotspot/share/prims/cdsoffsets.hpp
Normal 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
|
@ -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 },
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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) \
|
||||
|
@ -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 \
|
||||
|
45
test/hotspot/jtreg/runtime/appcds/AppCDSOptions.java
Normal file
45
test/hotspot/jtreg/runtime/appcds/AppCDSOptions.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
87
test/hotspot/jtreg/runtime/appcds/AppendClasspath.java
Normal file
87
test/hotspot/jtreg/runtime/appcds/AppendClasspath.java
Normal 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);
|
||||
}
|
||||
}
|
108
test/hotspot/jtreg/runtime/appcds/BootClassPathMismatch.java
Normal file
108
test/hotspot/jtreg/runtime/appcds/BootClassPathMismatch.java
Normal 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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
93
test/hotspot/jtreg/runtime/appcds/ClassLoaderTest.java
Normal file
93
test/hotspot/jtreg/runtime/appcds/ClassLoaderTest.java
Normal 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");
|
||||
}
|
||||
}
|
106
test/hotspot/jtreg/runtime/appcds/ClassPathAttr.java
Normal file
106
test/hotspot/jtreg/runtime/appcds/ClassPathAttr.java
Normal 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);
|
||||
}
|
||||
}
|
128
test/hotspot/jtreg/runtime/appcds/CommandLineFlagCombo.java
Normal file
128
test/hotspot/jtreg/runtime/appcds/CommandLineFlagCombo.java
Normal 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;
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
80
test/hotspot/jtreg/runtime/appcds/CompilerUtils.java
Normal file
80
test/hotspot/jtreg/runtime/appcds/CompilerUtils.java
Normal 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();
|
||||
}
|
||||
}
|
103
test/hotspot/jtreg/runtime/appcds/DumpClassList.java
Normal file
103
test/hotspot/jtreg/runtime/appcds/DumpClassList.java
Normal 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>");
|
||||
}
|
||||
}
|
11
test/hotspot/jtreg/runtime/appcds/ExtraSymbols.invalid_1.txt
Normal file
11
test/hotspot/jtreg/runtime/appcds/ExtraSymbols.invalid_1.txt
Normal 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
|
@ -0,0 +1,5 @@
|
||||
@SECTION: Symbol
|
||||
20 -1: isAlphaNumericString
|
||||
43 -1: (Ljava/lang/Class<*>;Ljava/lang/Class<*>;)Z
|
||||
15 -1: IntCumulateTask
|
||||
1 -1: \n
|
13
test/hotspot/jtreg/runtime/appcds/ExtraSymbols.invalid_3.txt
Normal file
13
test/hotspot/jtreg/runtime/appcds/ExtraSymbols.invalid_3.txt
Normal 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
|
89
test/hotspot/jtreg/runtime/appcds/ExtraSymbols.java
Normal file
89
test/hotspot/jtreg/runtime/appcds/ExtraSymbols.java
Normal 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);
|
||||
}
|
||||
}
|
10826
test/hotspot/jtreg/runtime/appcds/ExtraSymbols.symbols.txt
Normal file
10826
test/hotspot/jtreg/runtime/appcds/ExtraSymbols.symbols.txt
Normal file
File diff suppressed because one or more lines are too long
67
test/hotspot/jtreg/runtime/appcds/FieldAnnotationsTest.java
Normal file
67
test/hotspot/jtreg/runtime/appcds/FieldAnnotationsTest.java
Normal 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.");
|
||||
}
|
||||
}
|
118
test/hotspot/jtreg/runtime/appcds/FreeUnusedMetadata.java
Normal file
118
test/hotspot/jtreg/runtime/appcds/FreeUnusedMetadata.java
Normal 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");
|
||||
}
|
||||
}
|
72
test/hotspot/jtreg/runtime/appcds/HelloExtTest.java
Normal file
72
test/hotspot/jtreg/runtime/appcds/HelloExtTest.java
Normal 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);
|
||||
}
|
||||
}
|
44
test/hotspot/jtreg/runtime/appcds/HelloTest.java
Normal file
44
test/hotspot/jtreg/runtime/appcds/HelloTest.java
Normal 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");
|
||||
}
|
||||
}
|
63
test/hotspot/jtreg/runtime/appcds/IgnoreEmptyClassPaths.java
Normal file
63
test/hotspot/jtreg/runtime/appcds/IgnoreEmptyClassPaths.java
Normal 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);
|
||||
}
|
||||
}
|
235
test/hotspot/jtreg/runtime/appcds/JarBuilder.java
Normal file
235
test/hotspot/jtreg/runtime/appcds/JarBuilder.java
Normal 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());
|
||||
}
|
||||
}
|
107
test/hotspot/jtreg/runtime/appcds/JvmtiAddPath.java
Normal file
107
test/hotspot/jtreg/runtime/appcds/JvmtiAddPath.java
Normal 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");
|
||||
}
|
||||
}
|
81
test/hotspot/jtreg/runtime/appcds/MismatchedUseAppCDS.java
Normal file
81
test/hotspot/jtreg/runtime/appcds/MismatchedUseAppCDS.java
Normal 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);
|
||||
}
|
||||
}
|
52
test/hotspot/jtreg/runtime/appcds/MissingSuperTest.java
Normal file
52
test/hotspot/jtreg/runtime/appcds/MissingSuperTest.java
Normal 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");
|
||||
}
|
||||
}
|
144
test/hotspot/jtreg/runtime/appcds/MultiProcessSharing.java
Normal file
144
test/hotspot/jtreg/runtime/appcds/MultiProcessSharing.java
Normal 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);
|
||||
}
|
||||
|
||||
}
|
238
test/hotspot/jtreg/runtime/appcds/MultiReleaseJars.java
Normal file
238
test/hotspot/jtreg/runtime/appcds/MultiReleaseJars.java
Normal 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);
|
||||
}
|
||||
}
|
167
test/hotspot/jtreg/runtime/appcds/OldClassTest.java
Normal file
167
test/hotspot/jtreg/runtime/appcds/OldClassTest.java
Normal 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();
|
||||
}
|
||||
}
|
60
test/hotspot/jtreg/runtime/appcds/PackageSealing.java
Normal file
60
test/hotspot/jtreg/runtime/appcds/PackageSealing.java
Normal 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");
|
||||
}
|
||||
}
|
64
test/hotspot/jtreg/runtime/appcds/ParallelLoad2.java
Normal file
64
test/hotspot/jtreg/runtime/appcds/ParallelLoad2.java
Normal 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");
|
||||
}
|
||||
}
|
64
test/hotspot/jtreg/runtime/appcds/ParallelLoadTest.java
Normal file
64
test/hotspot/jtreg/runtime/appcds/ParallelLoadTest.java
Normal 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;
|
||||
}
|
||||
}
|
148
test/hotspot/jtreg/runtime/appcds/PrintSharedArchiveAndExit.java
Normal file
148
test/hotspot/jtreg/runtime/appcds/PrintSharedArchiveAndExit.java
Normal 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);
|
||||
}
|
||||
}
|
101
test/hotspot/jtreg/runtime/appcds/ProhibitedPackage.java
Normal file
101
test/hotspot/jtreg/runtime/appcds/ProhibitedPackage.java
Normal 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");
|
||||
}
|
||||
}
|
73
test/hotspot/jtreg/runtime/appcds/ProtectionDomain.java
Normal file
73
test/hotspot/jtreg/runtime/appcds/ProtectionDomain.java
Normal 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");
|
||||
}
|
||||
}
|
65
test/hotspot/jtreg/runtime/appcds/RewriteBytecodesTest.java
Normal file
65
test/hotspot/jtreg/runtime/appcds/RewriteBytecodesTest.java
Normal 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);
|
||||
}
|
||||
}
|
386
test/hotspot/jtreg/runtime/appcds/SharedArchiveConsistency.java
Normal file
386
test/hotspot/jtreg/runtime/appcds/SharedArchiveConsistency.java
Normal 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);
|
||||
}
|
||||
}
|
83
test/hotspot/jtreg/runtime/appcds/SharedArchiveFile.java
Normal file
83
test/hotspot/jtreg/runtime/appcds/SharedArchiveFile.java
Normal 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);
|
||||
}
|
||||
}
|
65
test/hotspot/jtreg/runtime/appcds/SharedBaseAddress.java
Normal file
65
test/hotspot/jtreg/runtime/appcds/SharedBaseAddress.java
Normal 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");
|
||||
}
|
||||
}
|
||||
}
|
79
test/hotspot/jtreg/runtime/appcds/SharedPackages.java
Normal file
79
test/hotspot/jtreg/runtime/appcds/SharedPackages.java
Normal 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");
|
||||
}
|
||||
}
|
||||
}
|
69
test/hotspot/jtreg/runtime/appcds/SignedJar.java
Normal file
69
test/hotspot/jtreg/runtime/appcds/SignedJar.java
Normal 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");
|
||||
}
|
||||
}
|
107
test/hotspot/jtreg/runtime/appcds/SpecifySysLoaderProp.java
Normal file
107
test/hotspot/jtreg/runtime/appcds/SpecifySysLoaderProp.java
Normal 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");
|
||||
}
|
||||
}
|
339
test/hotspot/jtreg/runtime/appcds/TestCommon.java
Normal file
339
test/hotspot/jtreg/runtime/appcds/TestCommon.java
Normal 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);
|
||||
}
|
||||
}
|
105
test/hotspot/jtreg/runtime/appcds/TraceLongClasspath.java
Normal file
105
test/hotspot/jtreg/runtime/appcds/TraceLongClasspath.java
Normal 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);
|
||||
}
|
||||
}
|
228
test/hotspot/jtreg/runtime/appcds/UseAppCDS.java
Normal file
228
test/hotspot/jtreg/runtime/appcds/UseAppCDS.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
30
test/hotspot/jtreg/runtime/appcds/UseAppCDS_Test.java
Normal file
30
test/hotspot/jtreg/runtime/appcds/UseAppCDS_Test.java
Normal 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]);
|
||||
}
|
||||
}
|
343
test/hotspot/jtreg/runtime/appcds/VerifierTest.java
Normal file
343
test/hotspot/jtreg/runtime/appcds/VerifierTest.java
Normal 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();
|
||||
}
|
||||
|
||||
}
|
38
test/hotspot/jtreg/runtime/appcds/VerifierTest_0.java
Normal file
38
test/hotspot/jtreg/runtime/appcds/VerifierTest_0.java
Normal 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
|
||||
*/
|
38
test/hotspot/jtreg/runtime/appcds/VerifierTest_1A.java
Normal file
38
test/hotspot/jtreg/runtime/appcds/VerifierTest_1A.java
Normal 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
|
||||
*/
|
38
test/hotspot/jtreg/runtime/appcds/VerifierTest_1B.java
Normal file
38
test/hotspot/jtreg/runtime/appcds/VerifierTest_1B.java
Normal 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
|
||||
*/
|
38
test/hotspot/jtreg/runtime/appcds/VerifierTest_2.java
Normal file
38
test/hotspot/jtreg/runtime/appcds/VerifierTest_2.java
Normal 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
|
||||
*/
|
50
test/hotspot/jtreg/runtime/appcds/WideIloadTest.java
Normal file
50
test/hotspot/jtreg/runtime/appcds/WideIloadTest.java
Normal 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");
|
||||
}
|
||||
}
|
56
test/hotspot/jtreg/runtime/appcds/WrongClasspath.java
Normal file
56
test/hotspot/jtreg/runtime/appcds/WrongClasspath.java
Normal 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);
|
||||
}
|
||||
}
|
@ -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");
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
VERSION: 1.0
|
||||
@SECTION: String
|
||||
26: shared_string_from_MyInner
|
@ -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");
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
VERSION: 1.0
|
||||
@SECTION: String
|
||||
25: GCStressApp_shared_string
|
@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
Manifest-Version: 1.0
|
||||
Premain-Class: InstrumentationRegisterClassFileTransformer
|
||||
Agent-Class: InstrumentationRegisterClassFileTransformer
|
||||
Can-Retransform-Classes: true
|
||||
Can-Redefine-Classes: true
|
@ -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);
|
||||
}
|
||||
}
|
43
test/hotspot/jtreg/runtime/appcds/cacheObject/MyOuter.java
Normal file
43
test/hotspot/jtreg/runtime/appcds/cacheObject/MyOuter.java
Normal 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");
|
||||
}
|
||||
}
|
||||
}
|
@ -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");
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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");
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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");
|
||||
}
|
||||
}
|
@ -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");
|
||||
}
|
||||
}
|
@ -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,
|
||||
};
|
||||
}
|
||||
}
|
@ -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
Loading…
x
Reference in New Issue
Block a user