8243586: Optimize calls to SystemDictionaryShared::define_shared_package for classpath
Define_shared_package only needs to be called once for each package in a jar specified in the shared class path. Reviewed-by: iklam, dholmes, minqi
This commit is contained in:
parent
4b85bd546e
commit
dc74336a65
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2020, 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,6 +27,7 @@
|
||||
|
||||
#include "classfile/moduleEntry.hpp"
|
||||
#include "oops/symbol.hpp"
|
||||
#include "runtime/atomic.hpp"
|
||||
#include "utilities/growableArray.hpp"
|
||||
#include "utilities/hashtable.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
@ -114,6 +115,8 @@ private:
|
||||
// Initial size of a package entry's list of qualified exports.
|
||||
enum {QUAL_EXP_SIZE = 43};
|
||||
|
||||
// a bit map indicating which CDS classpath entries have defined classes in this package.
|
||||
volatile int _defined_by_cds_in_class_path;
|
||||
public:
|
||||
void init() {
|
||||
_module = NULL;
|
||||
@ -121,6 +124,7 @@ public:
|
||||
_classpath_index = -1;
|
||||
_must_walk_exports = false;
|
||||
_qualified_exports = NULL;
|
||||
_defined_by_cds_in_class_path = 0;
|
||||
}
|
||||
|
||||
// package name
|
||||
@ -212,6 +216,24 @@ public:
|
||||
|
||||
void print(outputStream* st = tty);
|
||||
void verify();
|
||||
|
||||
static int max_index_for_defined_in_class_path() {
|
||||
return sizeof(int) * BitsPerByte;
|
||||
}
|
||||
|
||||
bool is_defined_by_cds_in_class_path(int idx) const {
|
||||
assert(idx < max_index_for_defined_in_class_path(), "sanity");
|
||||
return((Atomic::load(&_defined_by_cds_in_class_path) & ((int)1 << idx)) != 0);
|
||||
}
|
||||
void set_defined_by_cds_in_class_path(int idx) {
|
||||
assert(idx < max_index_for_defined_in_class_path(), "sanity");
|
||||
int old_val = 0;
|
||||
int new_val = 0;
|
||||
do {
|
||||
old_val = Atomic::load(&_defined_by_cds_in_class_path);
|
||||
new_val = old_val | ((int)1 << idx);
|
||||
} while (Atomic::cmpxchg(&_defined_by_cds_in_class_path, old_val, new_val) != old_val);
|
||||
}
|
||||
};
|
||||
|
||||
// The PackageEntryTable is a Hashtable containing a list of all packages defined
|
||||
|
@ -872,7 +872,19 @@ Handle SystemDictionaryShared::init_security_info(Handle class_loader, InstanceK
|
||||
// the corresponding SystemDictionaryShared::get_shared_xxx() function.
|
||||
Handle manifest = get_shared_jar_manifest(index, CHECK_(pd));
|
||||
Handle url = get_shared_jar_url(index, CHECK_(pd));
|
||||
define_shared_package(class_name, class_loader, manifest, url, CHECK_(pd));
|
||||
int index_offset = index - ClassLoaderExt::app_class_paths_start_index();
|
||||
if (index_offset < PackageEntry::max_index_for_defined_in_class_path()) {
|
||||
if (pkg_entry == NULL || !pkg_entry->is_defined_by_cds_in_class_path(index_offset)) {
|
||||
// define_shared_package only needs to be called once for each package in a jar specified
|
||||
// in the shared class path.
|
||||
define_shared_package(class_name, class_loader, manifest, url, CHECK_(pd));
|
||||
if (pkg_entry != NULL) {
|
||||
pkg_entry->set_defined_by_cds_in_class_path(index_offset);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
define_shared_package(class_name, class_loader, manifest, url, CHECK_(pd));
|
||||
}
|
||||
pd = get_shared_protection_domain(class_loader, index, url, CHECK_(pd));
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2020, 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,10 +27,8 @@
|
||||
* @summary AppCDS handling of package.
|
||||
* @requires vm.cds
|
||||
* @library /test/lib
|
||||
* @compile test-classes/C1.java
|
||||
* @compile test-classes/C2.java
|
||||
* @compile test-classes/PackageSealingTest.java
|
||||
* @compile test-classes/Hello.java
|
||||
* @compile test-classes/C1.java test-classes/C2.java test-classes/C3.java
|
||||
* test-classes/PackageSealingTest.java test-classes/Hello.java
|
||||
* @run driver PackageSealing
|
||||
*/
|
||||
|
||||
@ -39,10 +37,10 @@ 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",
|
||||
String[] classList = {"foo/C1", "pkg/C2", "PackageSealingTest"};
|
||||
String appJar = ClassFileInstaller.writeJar("foo-sealed.jar",
|
||||
ClassFileInstaller.Manifest.fromSourceFile("test-classes/package_seal.mf"),
|
||||
"PackageSealingTest", "sealed/pkg/C1", "pkg/C2");
|
||||
"PackageSealingTest", "foo/C1", "pkg/C2");
|
||||
|
||||
String helloJar = JarBuilder.getOrCreateHelloJar();
|
||||
String jars = helloJar + File.pathSeparator + appJar;
|
||||
@ -50,13 +48,46 @@ public class PackageSealing {
|
||||
// test shared package from -cp path
|
||||
TestCommon.testDump(jars, TestCommon.list(classList));
|
||||
OutputAnalyzer output;
|
||||
output = TestCommon.exec(jars, "PackageSealingTest");
|
||||
output = TestCommon.exec(jars, "PackageSealingTest",
|
||||
"foo/C1", "sealed", "pkg/C2", "notSealed");
|
||||
TestCommon.checkExec(output, "OK");
|
||||
|
||||
// test shared package from -Xbootclasspath/a
|
||||
TestCommon.dump(helloJar, TestCommon.list(classList),
|
||||
"-Xbootclasspath/a:" + appJar);
|
||||
output = TestCommon.exec(helloJar, "-Xbootclasspath/a:" + appJar, "PackageSealingTest");
|
||||
output = TestCommon.exec(helloJar, "-Xbootclasspath/a:" + appJar,
|
||||
"PackageSealingTest",
|
||||
"foo/C1", "sealed", "pkg/C2", "notSealed");
|
||||
TestCommon.checkExec(output, "OK");
|
||||
|
||||
// Test loading of two classes from the same package from different jars.
|
||||
// First loaded class is from a non-sealed package, the second loaded
|
||||
// class is from the same package but sealed.
|
||||
// The expected result is a SecurityException with a "sealing violation"
|
||||
// for the second class.
|
||||
classList[1] = "foo/C3"; // C3 is from a non-sealed package
|
||||
String[] classList2 = {"foo/C3", "foo/C1", "PackageSealingTest"};
|
||||
String nonSealedJar = ClassFileInstaller.writeJar("foo-unsealed.jar", "foo/C3");
|
||||
jars = helloJar + File.pathSeparator + nonSealedJar;
|
||||
TestCommon.testDump(jars, TestCommon.list(classList2));
|
||||
jars += File.pathSeparator + appJar;
|
||||
output = TestCommon.exec(jars, "-Xlog:class+load", "PackageSealingTest",
|
||||
"foo/C3", "notSealed", "foo/C1", "sealed");
|
||||
TestCommon.checkExec(output,
|
||||
"foo.C3 source: shared objects file",
|
||||
"sealing violation: can't seal package foo: already defined");
|
||||
|
||||
// Use the jar with the sealed package during dump time.
|
||||
// Reverse the class loading order during runtime: load the class in the
|
||||
// sealed package following by another class in the same package but unsealed.
|
||||
// Same "sealing violation should result in loading the second class.
|
||||
jars = helloJar + File.pathSeparator + appJar;
|
||||
TestCommon.testDump(jars, TestCommon.list(classList2));
|
||||
jars += File.pathSeparator + nonSealedJar;
|
||||
output = TestCommon.exec(jars, "-Xlog:class+load", "PackageSealingTest",
|
||||
"foo/C1", "sealed", "foo/C3", "notSealed");
|
||||
TestCommon.checkExec(output,
|
||||
"foo.C1 source: shared objects file",
|
||||
"sealing violation: package foo is sealed");
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2020, 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
|
||||
@ -22,7 +22,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package sealed.pkg;
|
||||
package foo;
|
||||
|
||||
public class C1 {
|
||||
}
|
||||
|
28
test/hotspot/jtreg/runtime/cds/appcds/test-classes/C3.java
Normal file
28
test/hotspot/jtreg/runtime/cds/appcds/test-classes/C3.java
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
package foo;
|
||||
|
||||
public class C3 {
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2020, 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
|
||||
@ -26,21 +26,24 @@ import java.lang.Package;
|
||||
|
||||
public class PackageSealingTest {
|
||||
public static void main(String args[]) {
|
||||
if (args.length != 4) {
|
||||
throw new RuntimeException("Expecting 4 arguments");
|
||||
}
|
||||
try {
|
||||
Class c1 = PackageSealingTest.class.forName("sealed.pkg.C1");
|
||||
Class c2 = PackageSealingTest.class.forName("pkg.C2");
|
||||
Class c1 = PackageSealingTest.class.forName(args[0].replace('/', '.'));
|
||||
Class c2 = PackageSealingTest.class.forName(args[2].replace('/', '.'));
|
||||
Package p1 = c1.getPackage();
|
||||
System.out.println("Package 1: " + p1.toString());
|
||||
Package p2 = c2.getPackage();
|
||||
System.out.println("Package 2: " + p2.toString());
|
||||
|
||||
if (!p1.isSealed()) {
|
||||
System.out.println("Failed: sealed.pkg is not sealed.");
|
||||
if (args[1].equals("sealed") && !p1.isSealed()) {
|
||||
System.out.println("Failed: " + p1.toString() + " is not sealed.");
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
if (p2.isSealed()) {
|
||||
System.out.println("Failed: pkg is sealed.");
|
||||
if (args[3].equals("notSealed") && p2.isSealed()) {
|
||||
System.out.println("Failed: " + p2.toString() + " is sealed.");
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
Manifest-Version: 1.0
|
||||
Created-By: 1.9.0-internal (Oracle Corporation)
|
||||
|
||||
Name: sealed/pkg/
|
||||
Name: foo/
|
||||
Sealed: true
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user