Skip to content

Commit

Permalink
[EagerAppCDS] enable classpath change by replacing given env var
Browse files Browse the repository at this point in the history
Summary: If user give environment vars and use
`-Dcom.alibaba.cds.cp.reloc.envs`, cds will change the
classpath by using given environment vars to transform
some paths in classpath.

Test Plan: ci jtreg
jdk/test/com/alibaba/quickstart/TestEnvVariableReplay.java
jdk/test/com/alibaba/quickstart/TestEnvVariableDump.java

Reviewed-by: lingjun-cg, yuleil

Issue: #595
  • Loading branch information
jia-wei-tang committed Oct 16, 2023
1 parent e000397 commit d82998f
Show file tree
Hide file tree
Showing 9 changed files with 461 additions and 102 deletions.
104 changes: 59 additions & 45 deletions hotspot/src/share/vm/classfile/sharedClassUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "runtime/arguments.hpp"
#include "runtime/java.hpp"
#include "runtime/os.hpp"
#include "runtime/quickStart.hpp"


class ManifestStream: public ResourceObj {
Expand Down Expand Up @@ -156,56 +157,69 @@ ClassPathSegment* SharedPathsMiscInfoExt::to_sorted_segments(const char* path, i
return cps;
}

bool SharedPathsMiscInfoExt::checkAPP(const char* path) {
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);
}
// Prefix is OK: E.g., dump with -cp foo.jar, but run with -cp foo.jar:bar.jar
if (AppCDSVerifyClassPathOrder) {
if (strncmp(path, appcp, len) != 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);
}
} else{
ResourceMark rm;
int app_seg_num = 0;
int path_seg_num = 0;
ClassPathSegment* app_cps = to_sorted_segments(appcp, app_seg_num);
ClassPathSegment* path_cps = to_sorted_segments(path, path_seg_num);
if (app_seg_num < path_seg_num) {
return fail("[APP classpath mismatch, actual: -Djava.class.path=", appcp);
} else {
int i = 0, j = 0;
while(i < path_seg_num && j < app_seg_num){
if (app_cps[j]._len != path_cps[i]._len){
j++;
} else {
int c = strncmp(app_cps[j]._start, path_cps[i]._start, app_cps[j]._len);
if (c == 0) {
i++;
j++;
} else if (c < 0) {
j++;
} else {
break;
}
}
}
if (i != path_seg_num) {
return fail("[APP classpath mismatch, actual: -Djava.class.path=", appcp);
}
}
}
return true;
}

bool SharedPathsMiscInfoExt::check(jint type, const char* path) {

switch (type) {
case APP:
{
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);
}
// Prefix is OK: E.g., dump with -cp foo.jar, but run with -cp foo.jar:bar.jar
if (AppCDSVerifyClassPathOrder) {
if (strncmp(path, appcp, len) != 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);
}
} else{
ResourceMark rm;
int app_seg_num = 0;
int path_seg_num = 0;
ClassPathSegment* app_cps = to_sorted_segments(appcp, app_seg_num);
ClassPathSegment* path_cps = to_sorted_segments(path, path_seg_num);
if (app_seg_num < path_seg_num) {
return fail("[APP classpath mismatch, actual: -Djava.class.path=", appcp);
} else {
int i = 0, j = 0;
while(i < path_seg_num && j < app_seg_num){
if (app_cps[j]._len != path_cps[i]._len){
j++;
} else {
int c = strncmp(app_cps[j]._start, path_cps[i]._start, app_cps[j]._len);
if (c == 0) {
i++;
j++;
} else if (c < 0) {
j++;
} else {
break;
}
}
}
if (i != path_seg_num) {
return fail("[APP classpath mismatch, actual: -Djava.class.path=", appcp);
}
}
if (QuickStart::need_convert_path_by_env()) {
int new_path_len = QuickStart::get_max_replaced_path_len(path) + 1;
char* new_path = NEW_C_HEAP_ARRAY(char, new_path_len, mtInternal);
QuickStart::convert_path_by_env(path, new_path);
ClassLoader::trace_class_path(tty, "new_path: ", new_path);
bool result = checkAPP(new_path);
FREE_C_HEAP_ARRAY(char, new_path, mtInternal);
return result;
} else {
return checkAPP(path);
}
}
break;
Expand Down
2 changes: 2 additions & 0 deletions hotspot/src/share/vm/classfile/sharedClassUtil.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ class SharedPathsMiscInfoExt : public SharedPathsMiscInfo {

virtual bool check(jint type, const char* path);

virtual bool checkAPP(const char* path);

void add_app_classpath(const char* path) {
add_path(path, APP);
}
Expand Down
13 changes: 12 additions & 1 deletion hotspot/src/share/vm/memory/filemap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "oops/objArrayOop.hpp"
#include "runtime/arguments.hpp"
#include "runtime/java.hpp"
#include "runtime/quickStart.hpp"
#include "runtime/os.hpp"
#include "services/memTracker.hpp"
#include "utilities/defaultStream.hpp"
Expand Down Expand Up @@ -264,6 +265,13 @@ bool FileMapInfo::validate_classpath_entry_table() {
SharedClassPathEntry* ent = shared_classpath(i);
struct stat st;
const char* name = ent->_name;
char* new_ent_name = QuickStart::replace_if_contains(name);
if (new_ent_name != NULL) {
if (TraceClassPaths || (TraceClassLoading && Verbose)) {
tty->print_cr("replace %s with %s", name, new_ent_name);
}
name = new_ent_name;
}
bool ok = true;
if (TraceClassPaths || (TraceClassLoading && Verbose)) {
tty->print_cr("[Checking shared classpath entry: %s]", name);
Expand All @@ -277,7 +285,7 @@ bool FileMapInfo::validate_classpath_entry_table() {
ok = false;
}
} else {
if (ent->_timestamp != st.st_mtime ||
if ((ent->_timestamp != st.st_mtime && !CDSIgnoreFileTimeCheck) ||
ent->_filesize != st.st_size) {
ok = false;
if (PrintSharedArchiveAndExit) {
Expand All @@ -290,6 +298,9 @@ bool FileMapInfo::validate_classpath_entry_table() {
}
}
}
if (new_ent_name != NULL) {
FREE_C_HEAP_ARRAY(char, new_ent_name, mtInternal);
}
if (ok) {
if (TraceClassPaths || (TraceClassLoading && Verbose)) {
tty->print_cr("[ok]");
Expand Down
2 changes: 2 additions & 0 deletions hotspot/src/share/vm/runtime/globals_ext.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@
"Ignore non-empty dir check in AppCDS") \
product(bool, CDSIgnoreBootClasspathDiff, false, \
"keep AppCDS on after appending boot classpath") \
product(bool, CDSIgnoreFileTimeCheck, false, \
"do not check timestamp of jar file when using CDS") \
\
product(bool, SuppressAppCDSErrors, false, \
"Suppress AppCDS errors during initialization; use warnings instead") \
Expand Down
Loading

0 comments on commit d82998f

Please sign in to comment.