mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8244540: Print more information with -XX:+PrintSharedArchiveAndExit
Reviewed-by: iklam, ccheung
This commit is contained in:
parent
e073486ffe
commit
928fa5b5f9
8 changed files with 294 additions and 11 deletions
|
@ -275,6 +275,13 @@ void SymbolTable::symbols_do(SymbolClosure *cl) {
|
|||
_local_table->do_safepoint_scan(sd);
|
||||
}
|
||||
|
||||
// Call function for all symbols in shared table. Used by -XX:+PrintSharedArchiveAndExit
|
||||
void SymbolTable::shared_symbols_do(SymbolClosure *cl) {
|
||||
SharedSymbolIterator iter(cl);
|
||||
_shared_table.iterate(&iter);
|
||||
_dynamic_shared_table.iterate(&iter);
|
||||
}
|
||||
|
||||
Symbol* SymbolTable::lookup_dynamic(const char* name,
|
||||
int len, unsigned int hash) {
|
||||
Symbol* sym = do_lookup(name, len, hash);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2021, 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
|
||||
|
@ -207,6 +207,7 @@ public:
|
|||
static void symbols_do(SymbolClosure *cl);
|
||||
|
||||
// Sharing
|
||||
static void shared_symbols_do(SymbolClosure *cl); // no safepoint iteration.
|
||||
private:
|
||||
static void copy_shared_symbol_table(GrowableArray<Symbol*>* symbols,
|
||||
CompactHashtableWriter* ch_table);
|
||||
|
|
|
@ -2224,6 +2224,24 @@ void SystemDictionaryShared::update_shared_entry(InstanceKlass* k, int id) {
|
|||
info->_id = id;
|
||||
}
|
||||
|
||||
const char* class_loader_name_for_shared(Klass* k) {
|
||||
assert(k != nullptr, "Sanity");
|
||||
assert(k->is_shared(), "Must be");
|
||||
assert(k->is_instance_klass(), "Must be");
|
||||
InstanceKlass* ik = InstanceKlass::cast(k);
|
||||
if (ik->is_shared_boot_class()) {
|
||||
return "boot_loader";
|
||||
} else if (ik->is_shared_platform_class()) {
|
||||
return "platform_loader";
|
||||
} else if (ik->is_shared_app_class()) {
|
||||
return "app_loader";
|
||||
} else if (ik->is_shared_unregistered_class()) {
|
||||
return "unregistered_loader";
|
||||
} else {
|
||||
return "unknown loader";
|
||||
}
|
||||
}
|
||||
|
||||
class SharedDictionaryPrinter : StackObj {
|
||||
outputStream* _st;
|
||||
int _index;
|
||||
|
@ -2232,23 +2250,25 @@ public:
|
|||
|
||||
void do_value(const RunTimeSharedClassInfo* record) {
|
||||
ResourceMark rm;
|
||||
_st->print_cr("%4d: %s", (_index++), record->_klass->external_name());
|
||||
_st->print_cr("%4d: %s %s", (_index++), record->_klass->external_name(),
|
||||
class_loader_name_for_shared(record->_klass));
|
||||
}
|
||||
int index() const { return _index; }
|
||||
};
|
||||
|
||||
class SharedLambdaDictionaryPrinter : StackObj {
|
||||
outputStream* _st;
|
||||
int _index;
|
||||
public:
|
||||
SharedLambdaDictionaryPrinter(outputStream* st) : _st(st), _index(0) {}
|
||||
SharedLambdaDictionaryPrinter(outputStream* st, int idx) : _st(st), _index(idx) {}
|
||||
|
||||
void do_value(const RunTimeLambdaProxyClassInfo* record) {
|
||||
if (record->proxy_klass_head()->lambda_proxy_is_available()) {
|
||||
ResourceMark rm;
|
||||
_st->print_cr("%4d: %s", (_index++), record->proxy_klass_head()->external_name());
|
||||
Klass* k = record->proxy_klass_head()->next_link();
|
||||
while (k != NULL) {
|
||||
_st->print_cr("%4d: %s", (_index++), k->external_name());
|
||||
Klass* k = record->proxy_klass_head();
|
||||
while (k != nullptr) {
|
||||
_st->print_cr("%4d: %s %s", (++_index), k->external_name(),
|
||||
class_loader_name_for_shared(k));
|
||||
k = k->next_link();
|
||||
}
|
||||
}
|
||||
|
@ -2262,15 +2282,30 @@ void SystemDictionaryShared::print_on(const char* prefix,
|
|||
outputStream* st) {
|
||||
st->print_cr("%sShared Dictionary", prefix);
|
||||
SharedDictionaryPrinter p(st);
|
||||
st->print_cr("%sShared Builtin Dictionary", prefix);
|
||||
builtin_dictionary->iterate(&p);
|
||||
st->print_cr("%sShared Unregistered Dictionary", prefix);
|
||||
unregistered_dictionary->iterate(&p);
|
||||
if (!lambda_dictionary->empty()) {
|
||||
st->print_cr("%sShared Lambda Dictionary", prefix);
|
||||
SharedLambdaDictionaryPrinter ldp(st);
|
||||
SharedLambdaDictionaryPrinter ldp(st, p.index());
|
||||
lambda_dictionary->iterate(&ldp);
|
||||
}
|
||||
}
|
||||
|
||||
void SystemDictionaryShared::print_shared_archive(outputStream* st, bool is_static) {
|
||||
if (UseSharedSpaces) {
|
||||
if (is_static) {
|
||||
print_on("", &_builtin_dictionary, &_unregistered_dictionary, &_lambda_proxy_class_dictionary, st);
|
||||
} else {
|
||||
if (DynamicArchive::is_mapped()) {
|
||||
print_on("", &_dynamic_builtin_dictionary, &_dynamic_unregistered_dictionary,
|
||||
&_dynamic_lambda_proxy_class_dictionary, st);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SystemDictionaryShared::print_on(outputStream* st) {
|
||||
if (UseSharedSpaces) {
|
||||
print_on("", &_builtin_dictionary, &_unregistered_dictionary, &_lambda_proxy_class_dictionary, st);
|
||||
|
|
|
@ -316,6 +316,7 @@ public:
|
|||
static void serialize_vm_classes(class SerializeClosure* soc);
|
||||
static void print() { return print_on(tty); }
|
||||
static void print_on(outputStream* st) NOT_CDS_RETURN;
|
||||
static void print_shared_archive(outputStream* st, bool is_static = true) NOT_CDS_RETURN;
|
||||
static void print_table_statistics(outputStream* st) NOT_CDS_RETURN;
|
||||
static bool empty_dumptime_table() NOT_CDS_RETURN_(true);
|
||||
static void start_dumping() NOT_CDS_RETURN;
|
||||
|
|
|
@ -544,6 +544,10 @@ public:
|
|||
header()->print(st);
|
||||
}
|
||||
|
||||
const char* vm_version() {
|
||||
return header()->jvm_ident();
|
||||
}
|
||||
|
||||
private:
|
||||
void seek_to_position(size_t pos);
|
||||
char* skip_first_path_entry(const char* path) NOT_CDS_RETURN_(NULL);
|
||||
|
|
|
@ -1328,6 +1328,34 @@ void MetaspaceShared::unmap_archive(FileMapInfo* mapinfo) {
|
|||
}
|
||||
}
|
||||
|
||||
// For -XX:PrintSharedArchiveAndExit
|
||||
class CountSharedSymbols : public SymbolClosure {
|
||||
private:
|
||||
int _count;
|
||||
public:
|
||||
CountSharedSymbols() : _count(0) {}
|
||||
void do_symbol(Symbol** sym) {
|
||||
_count++;
|
||||
}
|
||||
int total() { return _count; }
|
||||
|
||||
};
|
||||
|
||||
// For -XX:PrintSharedArchiveAndExit
|
||||
class CountSharedStrings : public OopClosure {
|
||||
private:
|
||||
int _count;
|
||||
public:
|
||||
CountSharedStrings() : _count(0) {}
|
||||
void do_oop(oop* p) {
|
||||
_count++;
|
||||
}
|
||||
void do_oop(narrowOop* p) {
|
||||
_count++;
|
||||
}
|
||||
int total() { return _count; }
|
||||
};
|
||||
|
||||
// Read the miscellaneous data from the shared file, and
|
||||
// serialize it out to its various destinations.
|
||||
|
||||
|
@ -1362,10 +1390,30 @@ void MetaspaceShared::initialize_shared_spaces() {
|
|||
}
|
||||
|
||||
if (PrintSharedArchiveAndExit) {
|
||||
if (PrintSharedDictionary) {
|
||||
tty->print_cr("\nShared classes:\n");
|
||||
SystemDictionaryShared::print_on(tty);
|
||||
// Print archive names
|
||||
if (dynamic_mapinfo != nullptr) {
|
||||
tty->print_cr("\n\nBase archive name: %s", Arguments::GetSharedArchivePath());
|
||||
tty->print_cr("Base archive version %d", static_mapinfo->version());
|
||||
} else {
|
||||
tty->print_cr("Static archive name: %s", static_mapinfo->full_path());
|
||||
tty->print_cr("Static archive version %d", static_mapinfo->version());
|
||||
}
|
||||
|
||||
SystemDictionaryShared::print_shared_archive(tty);
|
||||
if (dynamic_mapinfo != nullptr) {
|
||||
tty->print_cr("\n\nDynamic archive name: %s", dynamic_mapinfo->full_path());
|
||||
tty->print_cr("Dynamic archive version %d", dynamic_mapinfo->version());
|
||||
SystemDictionaryShared::print_shared_archive(tty, false/*dynamic*/);
|
||||
}
|
||||
|
||||
// collect shared symbols and strings
|
||||
CountSharedSymbols cl;
|
||||
SymbolTable::shared_symbols_do(&cl);
|
||||
tty->print_cr("Number of shared symbols: %d", cl.total());
|
||||
CountSharedStrings cs;
|
||||
StringTable::shared_oops_do(&cs);
|
||||
tty->print_cr("Number of shared strings: %d", cs.total());
|
||||
tty->print_cr("VM version: %s\r\n", static_mapinfo->vm_version());
|
||||
if (FileMapInfo::current_info() == NULL || _archive_loading_failed) {
|
||||
tty->print_cr("archive is invalid");
|
||||
vm_exit(1);
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Copyright (c) 2021, 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 -XX:+PrintSharedArchiveAndExit output for shared class.
|
||||
* @comment the code is mostly copied from HelloCustom
|
||||
* @requires vm.cds
|
||||
* @requires vm.cds.custom.loaders
|
||||
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
|
||||
* @compile test-classes/HelloUnload.java test-classes/CustomLoadee.java
|
||||
* @build sun.hotspot.WhiteBox jdk.test.lib.classloader.ClassUnloadCommon
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar hello.jar HelloUnload
|
||||
* jdk.test.lib.classloader.ClassUnloadCommon
|
||||
* jdk.test.lib.classloader.ClassUnloadCommon$1
|
||||
* jdk.test.lib.classloader.ClassUnloadCommon$TestFailure
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar hello_custom.jar CustomLoadee
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar WhiteBox.jar sun.hotspot.WhiteBox
|
||||
* @run driver PrintSharedArchiveAndExit
|
||||
*/
|
||||
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.helpers.ClassFileInstaller;
|
||||
import sun.hotspot.WhiteBox;
|
||||
|
||||
public class PrintSharedArchiveAndExit {
|
||||
public static void main(String[] args) throws Exception {
|
||||
run();
|
||||
}
|
||||
public static void run(String... extra_runtime_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[] {
|
||||
"HelloUnload",
|
||||
"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,
|
||||
TestCommon.concat(extra_runtime_args,
|
||||
// command-line arguments ...
|
||||
use_whitebox_jar,
|
||||
"-XX:+UnlockDiagnosticVMOptions",
|
||||
"-XX:+WhiteBoxAPI",
|
||||
"-XX:+PrintSharedArchiveAndExit",
|
||||
"HelloUnload", customJarPath, "true", "true"));
|
||||
output.shouldMatch(".* archive version \\d+")
|
||||
.shouldContain("java.lang.Object boot_loader")
|
||||
.shouldContain("HelloUnload app_loader")
|
||||
.shouldContain("CustomLoadee unregistered_loader")
|
||||
.shouldContain("Shared Builtin Dictionary")
|
||||
.shouldContain("Shared Unregistered Dictionary")
|
||||
.shouldMatch("Number of shared symbols: \\d+")
|
||||
.shouldMatch("Number of shared strings: \\d+")
|
||||
.shouldMatch("VM version: .*");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* Copyright (c) 2021, 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 dynamic archive with custom loader
|
||||
* @requires vm.cds
|
||||
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds /test/hotspot/jtreg/runtime/cds/appcds/customLoader/test-classes
|
||||
* @build HelloUnload CustomLoadee jdk.test.lib.classloader.ClassUnloadCommon
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar hello.jar HelloUnload
|
||||
* jdk.test.lib.classloader.ClassUnloadCommon
|
||||
* jdk.test.lib.classloader.ClassUnloadCommon$1
|
||||
* jdk.test.lib.classloader.ClassUnloadCommon$TestFailure
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar hello_custom.jar CustomLoadee
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar WhiteBox.jar sun.hotspot.WhiteBox
|
||||
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:./WhiteBox.jar PrintSharedArchiveAndExit
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import jdk.test.lib.cds.CDSTestUtils;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.helpers.ClassFileInstaller;
|
||||
|
||||
public class PrintSharedArchiveAndExit extends DynamicArchiveTestBase {
|
||||
private static final String ARCHIVE_NAME = CDSTestUtils.getOutputFileName("top.jsa");
|
||||
|
||||
public static void main(String... args) throws Exception {
|
||||
runTest(PrintSharedArchiveAndExit::testPrtNExit);
|
||||
}
|
||||
|
||||
public static void testPrtNExit() 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");
|
||||
String mainAppClass = "HelloUnload";
|
||||
|
||||
dump(ARCHIVE_NAME,
|
||||
use_whitebox_jar,
|
||||
"-XX:+UnlockDiagnosticVMOptions",
|
||||
"-XX:+WhiteBoxAPI",
|
||||
"-Xlog:cds",
|
||||
"-Xlog:cds+dynamic=debug",
|
||||
"-cp", appJar,
|
||||
mainAppClass, customJarPath, "false", "false")
|
||||
.assertNormalExit(output -> {
|
||||
output.shouldContain("Written dynamic archive 0x")
|
||||
.shouldNotContain("klasses.*=.*CustomLoadee")
|
||||
.shouldHaveExitValue(0);
|
||||
});
|
||||
|
||||
run(ARCHIVE_NAME,
|
||||
use_whitebox_jar,
|
||||
"-XX:+UnlockDiagnosticVMOptions",
|
||||
"-XX:+WhiteBoxAPI",
|
||||
"-Xlog:class+load",
|
||||
"-Xlog:cds=debug",
|
||||
"-Xlog:cds+dynamic=info",
|
||||
"-cp", appJar,
|
||||
"-XX:+PrintSharedArchiveAndExit",
|
||||
mainAppClass, customJarPath, "false", "true")
|
||||
.assertNormalExit(output -> {
|
||||
output.shouldHaveExitValue(0)
|
||||
.shouldMatch("Base archive name: .*.jsa") // given name ends with .jsa, maynot default name.
|
||||
.shouldMatch("Dynamic archive name: .*" + ARCHIVE_NAME)
|
||||
.shouldMatch("Base archive version \\d+")
|
||||
.shouldContain("java.lang.Object boot_loader")
|
||||
.shouldContain("HelloUnload app_loader")
|
||||
.shouldContain("CustomLoadee unregistered_loader")
|
||||
.shouldContain("Shared Builtin Dictionary")
|
||||
.shouldContain("Shared Unregistered Dictionary")
|
||||
.shouldMatch("Number of shared symbols: \\d+")
|
||||
.shouldMatch("Number of shared strings: \\d+")
|
||||
.shouldMatch("VM version: .*");
|
||||
});
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue