Skip to content
This repository has been archived by the owner on Oct 21, 2023. It is now read-only.

Fix JDK-8240567 - MethodTooLargeException thrown while creating a jlink image #1

Closed
wants to merge 15 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/testing.html
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ <h3 id="jtreg">JTReg</h3>
<p>Individual JTReg tests or directories containing JTReg tests can also be specified, like <code>test/hotspot/jtreg/native_sanity/JniVersion.java</code> or <code>hotspot/jtreg/native_sanity</code>. Just like for test root selection, you can either specify an absolute path (which can even point to JTReg tests outside the source tree), or a path relative to either the JDK top directory or the <code>test</code> directory. <code>hotspot</code> can be used as an alias for <code>hotspot/jtreg</code> here as well.</p>
<p>As long as the test groups or test paths can be uniquely resolved, you do not need to enter the <code>jtreg:</code> prefix. If this is not possible, or if you want to use a fully qualified test descriptor, add <code>jtreg:</code>, e.g. <code>jtreg:test/hotspot/jtreg/native_sanity</code>.</p>
<h3 id="gtest">Gtest</h3>
<p><strong>Note:</strong> To be able to run the Gtest suite, you need to configure your build to be able to find a proper version of the gtest source. For details, see the section <a href="building.html#running-tests">&quot;Running Tests&quot; in the build documentation</a>.</p>
<p>Since the Hotspot Gtest suite is so quick, the default is to run all tests. This is specified by just <code>gtest</code>, or as a fully qualified test descriptor <code>gtest:all</code>.</p>
<p>If you want, you can single out an individual test or a group of tests, for instance <code>gtest:LogDecorations</code> or <code>gtest:LogDecorations.level_test_vm</code>. This can be particularly useful if you want to run a shaky test repeatedly.</p>
<p>For Gtest, there is a separate test suite for each JVM variant. The JVM variant is defined by adding <code>/&lt;variant&gt;</code> to the test descriptor, e.g. <code>gtest:Log/client</code>. If you specify no variant, gtest will run once for each JVM variant present (e.g. server, client). So if you only have the server JVM present, then <code>gtest:all</code> will be equivalent to <code>gtest:all/server</code>.</p>
Expand Down
5 changes: 5 additions & 0 deletions doc/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,11 @@ use a fully qualified test descriptor, add `jtreg:`, e.g.

### Gtest

**Note:** To be able to run the Gtest suite, you need to configure your build to
be able to find a proper version of the gtest source. For details, see the
section ["Running Tests" in the build
documentation](building.html#running-tests).

Since the Hotspot Gtest suite is so quick, the default is to run all tests.
This is specified by just `gtest`, or as a fully qualified test descriptor
`gtest:all`.
Expand Down
18 changes: 17 additions & 1 deletion make/autoconf/lib-tests.m4
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,25 @@ AC_DEFUN_ONCE([LIB_TESTS_SETUP_GTEST],
AC_MSG_RESULT([no])
AC_MSG_ERROR([Can't find 'googlemock/include/gmock/gmock.h' under ${with_gtest} given with the --with-gtest option.])
else
GTEST_FRAMEWORK_SRC=${with_gtest}
GTEST_FRAMEWORK_SRC=$with_gtest
AC_MSG_RESULT([$GTEST_FRAMEWORK_SRC])
UTIL_FIXUP_PATH([GTEST_FRAMEWORK_SRC])

# Try to verify version. We require 1.8.1, but this can not be directly
# determined. :-( Instead, there are different, incorrect version
# numbers we can look for.
GTEST_VERSION_1="`$GREP GOOGLETEST_VERSION $GTEST_FRAMEWORK_SRC/CMakeLists.txt | $SED -E -e 's/set\(GOOGLETEST_VERSION (.*)\)/\1/'`"
if test "x$GTEST_VERSION_1" != "x1.9.0"; then
AC_MSG_ERROR([gtest at $GTEST_FRAMEWORK_SRC does not seem to be version 1.8.1])
fi

# We cannot grep for "AC_IN*T" as a literal since then m4 will treat it as a macro
# and expand it.
# Additional [] needed to keep m4 from mangling shell constructs.
[ GTEST_VERSION_2="`$GREP -A1 ^.C_INIT $GTEST_FRAMEWORK_SRC/configure.ac | $TAIL -n 1 | $SED -E -e 's/ +\[(.*)],/\1/'`" ]
if test "x$GTEST_VERSION_2" != "x1.8.0"; then
AC_MSG_ERROR([gtest at $GTEST_FRAMEWORK_SRC does not seem to be version 1.8.1 B])
fi
fi
fi
fi
Expand Down
9 changes: 3 additions & 6 deletions make/jdk/src/classes/build/tools/intpoly/FieldGen.java
Original file line number Diff line number Diff line change
Expand Up @@ -246,8 +246,7 @@ public int getCoefficient() {
}

public BigInteger getValue() {
return BigInteger.valueOf(2).pow(power)
.multiply(BigInteger.valueOf(coefficient));
return BigInteger.valueOf(coefficient).shiftLeft(power);
}

public String toString() {
Expand Down Expand Up @@ -663,14 +662,12 @@ private String generate(FieldParams params) throws IOException {
subtract = true;
}
String coefExpr = "BigInteger.valueOf(" + coefValue + ")";
String powExpr = "BigInteger.valueOf(2).pow(" + t.getPower() + ")";
String powExpr = ".shiftLeft(" + t.getPower() + ")";
String termExpr = "ERROR";
if (t.getPower() == 0) {
termExpr = coefExpr;
} else if (coefValue == 1) {
termExpr = powExpr;
} else {
termExpr = powExpr + ".multiply(" + coefExpr + ")";
termExpr = coefExpr + powExpr;
}
if (subtract) {
result.appendLine("result = result.subtract(" + termExpr + ");");
Expand Down
3 changes: 2 additions & 1 deletion src/hotspot/share/cds/cdsHeapVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,8 @@ CDSHeapVerifier::CDSHeapVerifier() : _archived_objs(0), _problems(0)

// This just points to an empty Map
ADD_EXCL("jdk/internal/reflect/Reflection", "methodFilterMap"); // E
ADD_EXCL("jdk/internal/util/StaticProperty", "FILE_ENCODING"); // C
ADD_EXCL("jdk/internal/util/StaticProperty", "FILE_ENCODING", // C
"JAVA_LOCALE_USE_OLD_ISO_CODES"); // C

// Integer for 0 and 1 are in java/lang/Integer$IntegerCache and are archived
ADD_EXCL("sun/invoke/util/ValueConversions", "ONE_INT", // E
Expand Down
9 changes: 8 additions & 1 deletion src/hotspot/share/cds/classListParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@
volatile Thread* ClassListParser::_parsing_thread = NULL;
ClassListParser* ClassListParser::_instance = NULL;

ClassListParser::ClassListParser(const char* file) : _id2klass_table(INITIAL_TABLE_SIZE, MAX_TABLE_SIZE) {
ClassListParser::ClassListParser(const char* file, ParseMode parse_mode) : _id2klass_table(INITIAL_TABLE_SIZE, MAX_TABLE_SIZE) {
log_info(cds)("Parsing %s%s", file,
(parse_mode == _parse_lambda_forms_invokers_only) ? " (lambda form invokers only)" : "");
_classlist_file = file;
_file = NULL;
// Use os::open() because neither fopen() nor os::fopen()
Expand All @@ -73,6 +75,7 @@ ClassListParser::ClassListParser(const char* file) : _id2klass_table(INITIAL_TAB
_line_no = 0;
_interfaces = new (ResourceObj::C_HEAP, mtClass) GrowableArray<int>(10, mtClass);
_indy_items = new (ResourceObj::C_HEAP, mtClass) GrowableArray<const char*>(9, mtClass);
_parse_mode = parse_mode;

// _instance should only be accessed by the thread that created _instance.
assert(_instance == NULL, "must be singleton");
Expand Down Expand Up @@ -104,6 +107,10 @@ int ClassListParser::parse(TRAPS) {
continue;
}

if (_parse_mode == _parse_lambda_forms_invokers_only) {
continue;
}

TempNewSymbol class_name_symbol = SymbolTable::new_symbol(_class_name);
if (_indy_items->length() > 0) {
// The current line is "@lambda-proxy class_name". Load the proxy class.
Expand Down
19 changes: 16 additions & 3 deletions src/hotspot/share/cds/classListParser.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2022, 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
Expand Down Expand Up @@ -67,6 +67,13 @@ class CDSIndyInfo {
};

class ClassListParser : public StackObj {
public:
enum ParseMode {
_parse_all,
_parse_lambda_forms_invokers_only,
};

private:
// Must be C_HEAP allocated -- we don't want nested resource allocations.
typedef ResizeableResourceHashtable<int, InstanceKlass*,
ResourceObj::C_HEAP, mtClassShared> ID2KlassTable;
Expand Down Expand Up @@ -107,6 +114,7 @@ class ClassListParser : public StackObj {
bool _interfaces_specified;
const char* _source;
bool _lambda_form_line;
ParseMode _parse_mode;

bool parse_int_option(const char* option_name, int* value);
bool parse_uint_option(const char* option_name, int* value);
Expand All @@ -124,10 +132,15 @@ class ClassListParser : public StackObj {
bool parse_one_line();
Klass* load_current_class(Symbol* class_name_symbol, TRAPS);

public:
ClassListParser(const char* file);
ClassListParser(const char* file, ParseMode _parse_mode);
~ClassListParser();

public:
static int parse_classlist(const char* classlist_path, ParseMode parse_mode, TRAPS) {
ClassListParser parser(classlist_path, parse_mode);
return parser.parse(THREAD); // returns the number of classes loaded.
}

static bool is_parsing_thread();
static ClassListParser* instance() {
assert(is_parsing_thread(), "call this only in the thread that created ClassListParsing::_instance");
Expand Down
72 changes: 40 additions & 32 deletions src/hotspot/share/cds/metaspaceShared.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -733,45 +733,59 @@ void MetaspaceShared::adjust_heap_sizes_for_dumping() {
}
#endif // INCLUDE_CDS_JAVA_HEAP && _LP64

void MetaspaceShared::get_default_classlist(char* default_classlist, const size_t buf_size) {
// Construct the path to the class list (in jre/lib)
// Walk up two directories from the location of the VM and
// optionally tack on "lib" (depending on platform)
os::jvm_path(default_classlist, (jint)(buf_size));
for (int i = 0; i < 3; i++) {
char *end = strrchr(default_classlist, *os::file_separator());
if (end != NULL) *end = '\0';
}
size_t classlist_path_len = strlen(default_classlist);
if (classlist_path_len >= 3) {
if (strcmp(default_classlist + classlist_path_len - 3, "lib") != 0) {
if (classlist_path_len < buf_size - 4) {
jio_snprintf(default_classlist + classlist_path_len,
buf_size - classlist_path_len,
"%slib", os::file_separator());
classlist_path_len += 4;
}
}
}
if (classlist_path_len < buf_size - 10) {
jio_snprintf(default_classlist + classlist_path_len,
buf_size - classlist_path_len,
"%sclasslist", os::file_separator());
}
}

void MetaspaceShared::preload_classes(TRAPS) {
char default_classlist[JVM_MAXPATHLEN];
const char* classlist_path;

get_default_classlist(default_classlist, sizeof(default_classlist));
if (SharedClassListFile == NULL) {
// Construct the path to the class list (in jre/lib)
// Walk up two directories from the location of the VM and
// optionally tack on "lib" (depending on platform)
os::jvm_path(default_classlist, sizeof(default_classlist));
for (int i = 0; i < 3; i++) {
char *end = strrchr(default_classlist, *os::file_separator());
if (end != NULL) *end = '\0';
}
int classlist_path_len = (int)strlen(default_classlist);
if (classlist_path_len >= 3) {
if (strcmp(default_classlist + classlist_path_len - 3, "lib") != 0) {
if (classlist_path_len < JVM_MAXPATHLEN - 4) {
jio_snprintf(default_classlist + classlist_path_len,
sizeof(default_classlist) - classlist_path_len,
"%slib", os::file_separator());
classlist_path_len += 4;
}
}
}
if (classlist_path_len < JVM_MAXPATHLEN - 10) {
jio_snprintf(default_classlist + classlist_path_len,
sizeof(default_classlist) - classlist_path_len,
"%sclasslist", os::file_separator());
}
classlist_path = default_classlist;
} else {
classlist_path = SharedClassListFile;
}

log_info(cds)("Loading classes to share ...");
_has_error_classes = false;
int class_count = parse_classlist(classlist_path, CHECK);
int class_count = ClassListParser::parse_classlist(classlist_path,
ClassListParser::_parse_all, CHECK);
if (ExtraSharedClassListFile) {
class_count += parse_classlist(ExtraSharedClassListFile, CHECK);
class_count += ClassListParser::parse_classlist(ExtraSharedClassListFile,
ClassListParser::_parse_all, CHECK);
}
if (classlist_path != default_classlist) {
struct stat statbuf;
if (os::stat(default_classlist, &statbuf) == 0) {
// File exists, let's use it.
class_count += ClassListParser::parse_classlist(default_classlist,
ClassListParser::_parse_lambda_forms_invokers_only, CHECK);
}
}

// Exercise the manifest processing code to ensure classes used by CDS at runtime
Expand Down Expand Up @@ -814,12 +828,6 @@ void MetaspaceShared::preload_and_dump_impl(TRAPS) {
VMThread::execute(&op);
}


int MetaspaceShared::parse_classlist(const char* classlist_path, TRAPS) {
ClassListParser parser(classlist_path);
return parser.parse(THREAD); // returns the number of classes loaded.
}

// Returns true if the class's status has changed.
bool MetaspaceShared::try_link_class(JavaThread* current, InstanceKlass* ik) {
ExceptionMark em(current);
Expand Down
4 changes: 1 addition & 3 deletions src/hotspot/share/cds/metaspaceShared.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,6 @@ class MetaspaceShared : AllStatic {
private:
static void preload_and_dump_impl(TRAPS) NOT_CDS_RETURN;
static void preload_classes(TRAPS) NOT_CDS_RETURN;
static int parse_classlist(const char * classlist_path,
TRAPS) NOT_CDS_RETURN_(0);


public:
static Symbol* symbol_rs_base() {
Expand Down Expand Up @@ -202,5 +199,6 @@ class MetaspaceShared : AllStatic {
ReservedSpace& class_space_rs);
static MapArchiveResult map_archive(FileMapInfo* mapinfo, char* mapped_base_address, ReservedSpace rs);
static void unmap_archive(FileMapInfo* mapinfo);
static void get_default_classlist(char* default_classlist, const size_t buf_size);
};
#endif // SHARE_CDS_METASPACESHARED_HPP
6 changes: 1 addition & 5 deletions src/hotspot/share/gc/g1/g1Analytics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,13 +241,9 @@ double G1Analytics::predict_dirtied_cards_rate_ms() const {
return predict_zero_bounded(_dirtied_cards_rate_ms_seq);
}

double G1Analytics::predict_young_card_merge_to_scan_ratio() const {
return predict_in_unit_interval(_young_card_merge_to_scan_ratio_seq);
}

size_t G1Analytics::predict_scan_card_num(size_t rs_length, bool for_young_gc) const {
if (for_young_gc || !enough_samples_available(_mixed_card_merge_to_scan_ratio_seq)) {
return (size_t)(rs_length * predict_young_card_merge_to_scan_ratio());
return (size_t)(rs_length * predict_in_unit_interval(_young_card_merge_to_scan_ratio_seq));
} else {
return (size_t)(rs_length * predict_in_unit_interval(_mixed_card_merge_to_scan_ratio_seq));
}
Expand Down
5 changes: 2 additions & 3 deletions src/hotspot/share/gc/g1/g1Analytics.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,10 +139,9 @@ class G1Analytics: public CHeapObj<mtGC> {

double predict_concurrent_refine_rate_ms() const;
double predict_dirtied_cards_rate_ms() const;
double predict_young_card_merge_to_scan_ratio() const;

double predict_mixed_card_merge_to_scan_ratio() const;

// Predict how many cards in a remembered set of length rs_length will need to
// be scanned in addition to the pending log buffer cards.
size_t predict_scan_card_num(size_t rs_length, bool for_young_gc) const;

double predict_card_merge_time_ms(size_t card_num, bool for_young_gc) const;
Expand Down
17 changes: 12 additions & 5 deletions src/hotspot/share/gc/g1/g1Policy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1010,17 +1010,24 @@ void G1Policy::record_young_gc_pause_end(bool evacuation_failed) {

double G1Policy::predict_base_time_ms(size_t pending_cards,
size_t rs_length) const {
size_t effective_scanned_cards = _analytics->predict_scan_card_num(rs_length, collector_state()->in_young_only_phase());
bool in_young_only_phase = collector_state()->in_young_only_phase();

double card_merge_time = _analytics->predict_card_merge_time_ms(pending_cards + rs_length, collector_state()->in_young_only_phase());
double card_scan_time = _analytics->predict_card_scan_time_ms(effective_scanned_cards, collector_state()->in_young_only_phase());
size_t unique_cards_from_rs = _analytics->predict_scan_card_num(rs_length, in_young_only_phase);
// Assume that all cards from the log buffers will be scanned, i.e. there are no
// duplicates in that set.
size_t effective_scanned_cards = unique_cards_from_rs + pending_cards;

double card_merge_time = _analytics->predict_card_merge_time_ms(pending_cards + rs_length, in_young_only_phase);
double card_scan_time = _analytics->predict_card_scan_time_ms(effective_scanned_cards, in_young_only_phase);
double constant_other_time = _analytics->predict_constant_other_time_ms();
double survivor_evac_time = predict_survivor_regions_evac_time();

double total_time = card_merge_time + card_scan_time + constant_other_time + survivor_evac_time;

log_trace(gc, ergo, heap)("Predicted base time: total %f lb_cards %zu rs_length %zu effective_scanned_cards %zu card_merge_time %f card_scan_time %f constant_other_time %f survivor_evac_time %f",
total_time, pending_cards, rs_length, effective_scanned_cards, card_merge_time, card_scan_time, constant_other_time, survivor_evac_time);
log_trace(gc, ergo, heap)("Predicted base time: total %f lb_cards %zu rs_length %zu effective_scanned_cards %zu "
"card_merge_time %f card_scan_time %f constant_other_time %f survivor_evac_time %f",
total_time, pending_cards, rs_length, effective_scanned_cards,
card_merge_time, card_scan_time, constant_other_time, survivor_evac_time);
return total_time;
}

Expand Down
1 change: 1 addition & 0 deletions src/hotspot/share/jvmci/jvmciEnv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1616,6 +1616,7 @@ CodeBlob* JVMCIEnv::get_code_blob(JVMCIObject obj) {
// nmethod in the code cache.
set_InstalledCode_address(obj, 0);
set_InstalledCode_entryPoint(obj, 0);
set_HotSpotInstalledCode_codeStart(obj, 0);
}
return nm;
}
Expand Down
2 changes: 2 additions & 0 deletions src/hotspot/share/jvmci/jvmciRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -820,11 +820,13 @@ void JVMCINMethodData::invalidate_nmethod_mirror(nmethod* nm) {
// an InvalidInstalledCodeException.
HotSpotJVMCI::InstalledCode::set_address(jvmciEnv, nmethod_mirror, 0);
HotSpotJVMCI::InstalledCode::set_entryPoint(jvmciEnv, nmethod_mirror, 0);
HotSpotJVMCI::HotSpotInstalledCode::set_codeStart(jvmciEnv, nmethod_mirror, 0);
} else if (nm->is_not_entrant()) {
// Zero the entry point so any new invocation will fail but keep
// the address link around that so that existing activations can
// be deoptimized via the mirror (i.e. JVMCIEnv::invalidate_installed_code).
HotSpotJVMCI::InstalledCode::set_entryPoint(jvmciEnv, nmethod_mirror, 0);
HotSpotJVMCI::HotSpotInstalledCode::set_codeStart(jvmciEnv, nmethod_mirror, 0);
}
}

Expand Down
9 changes: 5 additions & 4 deletions src/java.base/share/classes/java/nio/X-Buffer.java.template
Original file line number Diff line number Diff line change
Expand Up @@ -150,10 +150,11 @@ import jdk.internal.util.ArraysSupport;
* values, for example, this class defines:
*
* <blockquote><pre>
* float {@link #getFloat()}
* float {@link #getFloat(int) getFloat(int index)}
* void {@link #putFloat(float) putFloat(float f)}
* void {@link #putFloat(int,float) putFloat(int index, float f)}</pre></blockquote>
* float {@link #getFloat()}
* float {@link #getFloat(int) getFloat(int index)}
* ByteBuffer {@link #putFloat(float) putFloat(float f)}
* ByteBuffer {@link #putFloat(int,float) putFloat(int index, float f)}
* </pre></blockquote>
*
* <p> Corresponding methods are defined for the types {@code char,
* short, int, long}, and {@code double}. The index
Expand Down
Loading