8267556: Enhance class paths check during runtime

Reviewed-by: minqi, iklam
This commit is contained in:
Calvin Cheung 2021-06-10 19:50:44 +00:00
parent 8c8422e0f8
commit 4fd2a14997
7 changed files with 100 additions and 6 deletions

View File

@ -32,6 +32,7 @@
#include "cds/metaspaceShared.hpp"
#include "classfile/altHashing.hpp"
#include "classfile/classFileStream.hpp"
#include "classfile/classLoader.hpp"
#include "classfile/classLoader.inline.hpp"
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/classLoaderExt.hpp"
@ -240,6 +241,7 @@ void FileMapHeader::populate(FileMapInfo* mapinfo, size_t core_region_alignment)
_verify_local = BytecodeVerificationLocal;
_verify_remote = BytecodeVerificationRemote;
_has_platform_or_app_classes = ClassLoaderExt::has_platform_or_app_classes();
_has_non_jar_in_classpath = ClassLoaderExt::has_non_jar_in_classpath();
_requested_base_address = (char*)SharedBaseAddress;
_mapped_base_address = (char*)SharedBaseAddress;
_allow_archiving_with_java_agent = AllowArchivingWithJavaAgent;
@ -293,6 +295,7 @@ void FileMapHeader::print(outputStream* st) {
st->print_cr("- verify_local: %d", _verify_local);
st->print_cr("- verify_remote: %d", _verify_remote);
st->print_cr("- has_platform_or_app_classes: %d", _has_platform_or_app_classes);
st->print_cr("- has_non_jar_in_classpath: %d", _has_non_jar_in_classpath);
st->print_cr("- requested_base_address: " INTPTR_FORMAT, p2i(_requested_base_address));
st->print_cr("- mapped_base_address: " INTPTR_FORMAT, p2i(_mapped_base_address));
st->print_cr("- allow_archiving_with_java_agent:%d", _allow_archiving_with_java_agent);
@ -717,13 +720,25 @@ int FileMapInfo::num_paths(const char* path) {
GrowableArray<const char*>* FileMapInfo::create_path_array(const char* paths) {
GrowableArray<const char*>* path_array = new GrowableArray<const char*>(10);
JavaThread* current = JavaThread::current();
ClasspathStream cp_stream(paths);
bool non_jar_in_cp = header()->has_non_jar_in_classpath();
while (cp_stream.has_next()) {
const char* path = cp_stream.get_next();
struct stat st;
if (os::stat(path, &st) == 0) {
path_array->append(path);
if (!non_jar_in_cp) {
struct stat st;
if (os::stat(path, &st) == 0) {
path_array->append(path);
}
} else {
const char* canonical_path = ClassLoader::get_canonical_path(path, current);
if (canonical_path != NULL) {
char* error_msg = NULL;
jzfile* zip = ClassLoader::open_zip_file(canonical_path, &error_msg, current);
if (zip != NULL && error_msg == NULL) {
path_array->append(path);
}
}
}
}
return path_array;

View File

@ -203,6 +203,7 @@ class FileMapHeader: private CDSFileMapHeaderBase {
address _heap_begin; // heap begin at dump time.
address _heap_end; // heap end at dump time.
bool _base_archive_is_default; // indicates if the base archive is the system default one
bool _has_non_jar_in_classpath; // non-jar file entry exists in classpath
// The following fields are all sanity checks for whether this archive
// will function correctly with this JVM and the bootclasspath it's
@ -272,6 +273,7 @@ public:
char* requested_base_address() const { return _requested_base_address; }
char* mapped_base_address() const { return _mapped_base_address; }
bool has_platform_or_app_classes() const { return _has_platform_or_app_classes; }
bool has_non_jar_in_classpath() const { return _has_non_jar_in_classpath; }
size_t ptrmap_size_in_bits() const { return _ptrmap_size_in_bits; }
bool compressed_oops() const { return _compressed_oops; }
bool compressed_class_pointers() const { return _compressed_class_ptrs; }

View File

@ -736,6 +736,9 @@ ClassPathEntry* ClassLoader::create_class_path_entry(JavaThread* current,
if (zip != NULL && error_msg == NULL) {
new_entry = new ClassPathZipEntry(zip, path, is_boot_append, from_class_path_attr);
} else {
#if INCLUDE_CDS
ClassLoaderExt::set_has_non_jar_in_classpath();
#endif
return NULL;
}
log_info(class, path)("opened: %s", path);

View File

@ -254,9 +254,9 @@ class ClassLoader: AllStatic {
static int _libzip_loaded; // used to sync loading zip.
static void release_load_zip_library();
static inline void load_zip_library_if_needed();
static jzfile* open_zip_file(const char* canonical_path, char** error_msg, JavaThread* thread);
public:
static jzfile* open_zip_file(const char* canonical_path, char** error_msg, JavaThread* thread);
static ClassPathEntry* create_class_path_entry(JavaThread* current,
const char *path, const struct stat* st,
bool is_boot_append,

View File

@ -56,6 +56,7 @@ jshort ClassLoaderExt::_app_module_paths_start_index = ClassLoaderExt::max_class
jshort ClassLoaderExt::_max_used_path_index = 0;
bool ClassLoaderExt::_has_app_classes = false;
bool ClassLoaderExt::_has_platform_classes = false;
bool ClassLoaderExt::_has_non_jar_in_classpath = false;
void ClassLoaderExt::append_boot_classpath(ClassPathEntry* new_entry) {
if (UseSharedSpaces) {

View File

@ -56,6 +56,7 @@ private:
static bool _has_app_classes;
static bool _has_platform_classes;
static bool _has_non_jar_in_classpath;
static char* read_manifest(JavaThread* current, ClassPathEntry* entry, jint *manifest_size, bool clean_text);
static ClassPathEntry* find_classpath_entry_from_cache(JavaThread* current, const char* path);
@ -107,6 +108,10 @@ public:
return _has_app_classes || _has_platform_classes;
}
static bool has_non_jar_in_classpath() {
return _has_non_jar_in_classpath;
}
static void record_result(const s2 classpath_index, InstanceKlass* result);
static InstanceKlass* load_class(Symbol* h_name, const char* path, TRAPS);
static void set_has_app_classes() {
@ -115,7 +120,10 @@ public:
static void set_has_platform_classes() {
_has_platform_classes = true;
}
#endif
static void set_has_non_jar_in_classpath() {
_has_non_jar_in_classpath = true;
}
#endif // INCLUDE_CDS
};
#endif // SHARE_CLASSFILE_CLASSLOADEREXT_HPP

View File

@ -0,0 +1,65 @@
/*
* 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 Non jar file in the classpath will be skipped during dump time and runtime.
* @requires vm.cds
* @library /test/lib
* @compile test-classes/Hello.java
* @compile test-classes/HelloMore.java
* @run driver NonJarInClasspath
*/
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import jdk.test.lib.cds.CDSTestUtils;
import jdk.test.lib.process.OutputAnalyzer;
public class NonJarInClasspath {
public static void main(String[] args) throws Exception {
String appJar = JarBuilder.getOrCreateHelloJar();
String appJar2 = JarBuilder.build("hellomore", "HelloMore");
String outDir = CDSTestUtils.getOutputDir();
String newFile = "non-exist.jar";
String nonJarPath = outDir + File.separator + newFile;
String classPath = appJar + File.pathSeparator + nonJarPath + File.pathSeparator + appJar2;
File nonJar = new File(outDir, newFile);
nonJar.createNewFile();
TestCommon.testDump(classPath, TestCommon.list("Hello", "HelloMore"));
TestCommon.run(
"-cp", classPath,
"-Xlog:class+load",
"Hello")
.assertNormalExit(out -> {
out.shouldContain("Hello source: shared objects file");
});
}
}