mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 14:54:52 +02:00
8266851: Implement JEP 403: Strongly Encapsulate JDK Internals
Co-authored-by: Alan Bateman <alanb@openjdk.org> Reviewed-by: mchung, alanb, hseigel
This commit is contained in:
parent
8c4719a588
commit
e63023546a
26 changed files with 50 additions and 2842 deletions
|
@ -1330,7 +1330,6 @@ bool Arguments::add_property(const char* prop, PropertyWriteable writeable, Prop
|
||||||
log_info(cds)("optimized module handling: disabled due to incompatible property: %s=%s", key, value);
|
log_info(cds)("optimized module handling: disabled due to incompatible property: %s=%s", key, value);
|
||||||
}
|
}
|
||||||
if (strcmp(key, "jdk.module.showModuleResolution") == 0 ||
|
if (strcmp(key, "jdk.module.showModuleResolution") == 0 ||
|
||||||
strcmp(key, "jdk.module.illegalAccess") == 0 ||
|
|
||||||
strcmp(key, "jdk.module.validation") == 0 ||
|
strcmp(key, "jdk.module.validation") == 0 ||
|
||||||
strcmp(key, "java.system.class.loader") == 0) {
|
strcmp(key, "java.system.class.loader") == 0) {
|
||||||
MetaspaceShared::disable_full_module_graph();
|
MetaspaceShared::disable_full_module_graph();
|
||||||
|
@ -2061,8 +2060,7 @@ bool Arguments::parse_uintx(const char* value,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Arguments::create_module_property(const char* prop_name, const char* prop_value, PropertyInternal internal) {
|
bool Arguments::create_module_property(const char* prop_name, const char* prop_value, PropertyInternal internal) {
|
||||||
assert(is_internal_module_property(prop_name) ||
|
assert(is_internal_module_property(prop_name), "unknown module property: '%s'", prop_name);
|
||||||
strcmp(prop_name, "jdk.module.illegalAccess") == 0, "unknown module property: '%s'", prop_name);
|
|
||||||
size_t prop_len = strlen(prop_name) + strlen(prop_value) + 2;
|
size_t prop_len = strlen(prop_name) + strlen(prop_value) + 2;
|
||||||
char* property = AllocateHeap(prop_len, mtArguments);
|
char* property = AllocateHeap(prop_len, mtArguments);
|
||||||
int ret = jio_snprintf(property, prop_len, "%s=%s", prop_name, prop_value);
|
int ret = jio_snprintf(property, prop_len, "%s=%s", prop_name, prop_value);
|
||||||
|
@ -2427,10 +2425,9 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, bool* patch_m
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
} else if (match_option(option, "--illegal-access=", &tail)) {
|
} else if (match_option(option, "--illegal-access=", &tail)) {
|
||||||
warning("Option --illegal-access is deprecated and will be removed in a future release.");
|
char version[256];
|
||||||
if (!create_module_property("jdk.module.illegalAccess", tail, ExternalProperty)) {
|
JDK_Version::jdk(17).to_string(version, sizeof(version));
|
||||||
return JNI_ENOMEM;
|
warning("Ignoring option %s; support was removed in %s", option->optionString, version);
|
||||||
}
|
|
||||||
// -agentlib and -agentpath
|
// -agentlib and -agentpath
|
||||||
} else if (match_option(option, "-agentlib:", &tail) ||
|
} else if (match_option(option, "-agentlib:", &tail) ||
|
||||||
(is_absolute_path = match_option(option, "-agentpath:", &tail))) {
|
(is_absolute_path = match_option(option, "-agentpath:", &tail))) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -56,8 +56,6 @@ import jdk.internal.loader.BuiltinClassLoader;
|
||||||
import jdk.internal.loader.BootLoader;
|
import jdk.internal.loader.BootLoader;
|
||||||
import jdk.internal.loader.ClassLoaders;
|
import jdk.internal.loader.ClassLoaders;
|
||||||
import jdk.internal.misc.CDS;
|
import jdk.internal.misc.CDS;
|
||||||
import jdk.internal.misc.VM;
|
|
||||||
import jdk.internal.module.IllegalAccessLogger;
|
|
||||||
import jdk.internal.module.ModuleLoaderMap;
|
import jdk.internal.module.ModuleLoaderMap;
|
||||||
import jdk.internal.module.ServicesCatalog;
|
import jdk.internal.module.ServicesCatalog;
|
||||||
import jdk.internal.module.Resources;
|
import jdk.internal.module.Resources;
|
||||||
|
@ -903,27 +901,8 @@ public final class Module implements AnnotatedElement {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// check if the package is already exported/open to other
|
// check if the package is already exported/open to other
|
||||||
if (implIsExportedOrOpen(pn, other, open)) {
|
if (implIsExportedOrOpen(pn, other, open))
|
||||||
|
return;
|
||||||
// if the package is exported/open for illegal access then we need
|
|
||||||
// to record that it has also been exported/opened reflectively so
|
|
||||||
// that the IllegalAccessLogger doesn't emit a warning.
|
|
||||||
boolean needToAdd = false;
|
|
||||||
if (!other.isNamed()) {
|
|
||||||
IllegalAccessLogger l = IllegalAccessLogger.illegalAccessLogger();
|
|
||||||
if (l != null) {
|
|
||||||
if (open) {
|
|
||||||
needToAdd = l.isOpenForIllegalAccess(this, pn);
|
|
||||||
} else {
|
|
||||||
needToAdd = l.isExportedForIllegalAccess(this, pn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!needToAdd) {
|
|
||||||
// nothing to do
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// can only export a package in the module
|
// can only export a package in the module
|
||||||
if (!descriptor.packages().contains(pn)) {
|
if (!descriptor.packages().contains(pn)) {
|
||||||
|
|
|
@ -28,7 +28,6 @@ package java.lang.invoke;
|
||||||
import jdk.internal.access.SharedSecrets;
|
import jdk.internal.access.SharedSecrets;
|
||||||
import jdk.internal.misc.Unsafe;
|
import jdk.internal.misc.Unsafe;
|
||||||
import jdk.internal.misc.VM;
|
import jdk.internal.misc.VM;
|
||||||
import jdk.internal.module.IllegalAccessLogger;
|
|
||||||
import jdk.internal.org.objectweb.asm.ClassReader;
|
import jdk.internal.org.objectweb.asm.ClassReader;
|
||||||
import jdk.internal.org.objectweb.asm.Opcodes;
|
import jdk.internal.org.objectweb.asm.Opcodes;
|
||||||
import jdk.internal.org.objectweb.asm.Type;
|
import jdk.internal.org.objectweb.asm.Type;
|
||||||
|
@ -262,13 +261,6 @@ public class MethodHandles {
|
||||||
// M2 != M1, set previous lookup class to M1 and drop MODULE access
|
// M2 != M1, set previous lookup class to M1 and drop MODULE access
|
||||||
newPreviousClass = callerClass;
|
newPreviousClass = callerClass;
|
||||||
newModes &= ~Lookup.MODULE;
|
newModes &= ~Lookup.MODULE;
|
||||||
|
|
||||||
if (!callerModule.isNamed() && targetModule.isNamed()) {
|
|
||||||
IllegalAccessLogger logger = IllegalAccessLogger.illegalAccessLogger();
|
|
||||||
if (logger != null) {
|
|
||||||
logger.logIfOpenedForIllegalAccess(caller, targetClass);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return Lookup.newLookup(targetClass, newPreviousClass, newModes);
|
return Lookup.newLookup(targetClass, newPreviousClass, newModes);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,6 @@ import java.security.AccessController;
|
||||||
|
|
||||||
import jdk.internal.access.SharedSecrets;
|
import jdk.internal.access.SharedSecrets;
|
||||||
import jdk.internal.misc.VM;
|
import jdk.internal.misc.VM;
|
||||||
import jdk.internal.module.IllegalAccessLogger;
|
|
||||||
import jdk.internal.reflect.CallerSensitive;
|
import jdk.internal.reflect.CallerSensitive;
|
||||||
import jdk.internal.reflect.Reflection;
|
import jdk.internal.reflect.Reflection;
|
||||||
import jdk.internal.reflect.ReflectionFactory;
|
import jdk.internal.reflect.ReflectionFactory;
|
||||||
|
@ -324,7 +323,6 @@ public class AccessibleObject implements AnnotatedElement {
|
||||||
if (isClassPublic && declaringModule.isExported(pn, callerModule)) {
|
if (isClassPublic && declaringModule.isExported(pn, callerModule)) {
|
||||||
// member is public
|
// member is public
|
||||||
if (Modifier.isPublic(modifiers)) {
|
if (Modifier.isPublic(modifiers)) {
|
||||||
logIfExportedForIllegalAccess(caller, declaringClass);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -332,14 +330,12 @@ public class AccessibleObject implements AnnotatedElement {
|
||||||
if (Modifier.isProtected(modifiers)
|
if (Modifier.isProtected(modifiers)
|
||||||
&& Modifier.isStatic(modifiers)
|
&& Modifier.isStatic(modifiers)
|
||||||
&& isSubclassOf(caller, declaringClass)) {
|
&& isSubclassOf(caller, declaringClass)) {
|
||||||
logIfExportedForIllegalAccess(caller, declaringClass);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// package is open to caller
|
// package is open to caller
|
||||||
if (declaringModule.isOpen(pn, callerModule)) {
|
if (declaringModule.isOpen(pn, callerModule)) {
|
||||||
logIfOpenedForIllegalAccess(caller, declaringClass);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -373,30 +369,6 @@ public class AccessibleObject implements AnnotatedElement {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void logIfOpenedForIllegalAccess(Class<?> caller, Class<?> declaringClass) {
|
|
||||||
Module callerModule = caller.getModule();
|
|
||||||
Module targetModule = declaringClass.getModule();
|
|
||||||
// callerModule is null during early startup
|
|
||||||
if (callerModule != null && !callerModule.isNamed() && targetModule.isNamed()) {
|
|
||||||
IllegalAccessLogger logger = IllegalAccessLogger.illegalAccessLogger();
|
|
||||||
if (logger != null) {
|
|
||||||
logger.logIfOpenedForIllegalAccess(caller, declaringClass, this::toShortString);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void logIfExportedForIllegalAccess(Class<?> caller, Class<?> declaringClass) {
|
|
||||||
Module callerModule = caller.getModule();
|
|
||||||
Module targetModule = declaringClass.getModule();
|
|
||||||
// callerModule is null during early startup
|
|
||||||
if (callerModule != null && !callerModule.isNamed() && targetModule.isNamed()) {
|
|
||||||
IllegalAccessLogger logger = IllegalAccessLogger.illegalAccessLogger();
|
|
||||||
if (logger != null) {
|
|
||||||
logger.logIfExportedForIllegalAccess(caller, declaringClass, this::toShortString);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a short descriptive string to describe this object in log messages.
|
* Returns a short descriptive string to describe this object in log messages.
|
||||||
*/
|
*/
|
||||||
|
@ -743,9 +715,6 @@ public class AccessibleObject implements AnnotatedElement {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// access okay
|
|
||||||
logIfExportedForIllegalAccess(caller, memberClass);
|
|
||||||
|
|
||||||
// Success: Update the cache.
|
// Success: Update the cache.
|
||||||
Object cache = (targetClass != null
|
Object cache = (targetClass != null
|
||||||
&& Modifier.isProtected(modifiers)
|
&& Modifier.isProtected(modifiers)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -68,14 +68,4 @@ class ExplodedSystemModules implements SystemModules {
|
||||||
public Map<String, Set<String>> moduleReads() {
|
public Map<String, Set<String>> moduleReads() {
|
||||||
throw new InternalError();
|
throw new InternalError();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, Set<String>> concealedPackagesToOpen() {
|
|
||||||
return Map.of();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, Set<String>> exportedPackagesToOpen() {
|
|
||||||
return Map.of();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,407 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2017, 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. Oracle designates this
|
|
||||||
* particular file as subject to the "Classpath" exception as provided
|
|
||||||
* by Oracle in the LICENSE file that accompanied this code.
|
|
||||||
*
|
|
||||||
* 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 jdk.internal.module;
|
|
||||||
|
|
||||||
import java.io.PrintStream;
|
|
||||||
import java.lang.invoke.MethodHandles;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.security.AccessController;
|
|
||||||
import java.security.CodeSource;
|
|
||||||
import java.security.PrivilegedAction;
|
|
||||||
import java.security.ProtectionDomain;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.StringJoiner;
|
|
||||||
import java.util.WeakHashMap;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
import static java.util.Collections.*;
|
|
||||||
|
|
||||||
import jdk.internal.access.JavaLangAccess;
|
|
||||||
import jdk.internal.access.SharedSecrets;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Supports logging of access to members of exported and concealed packages
|
|
||||||
* that are opened to code in unnamed modules for illegal access.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public final class IllegalAccessLogger {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Logger modes
|
|
||||||
*/
|
|
||||||
public enum Mode {
|
|
||||||
/**
|
|
||||||
* Prints a warning when an illegal access succeeds and then
|
|
||||||
* discards the logger so that there is no further output.
|
|
||||||
*/
|
|
||||||
ONESHOT,
|
|
||||||
/**
|
|
||||||
* Print warnings when illegal access succeeds
|
|
||||||
*/
|
|
||||||
WARN,
|
|
||||||
/**
|
|
||||||
* Prints warnings and a stack trace when illegal access succeeds
|
|
||||||
*/
|
|
||||||
DEBUG,
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A builder for IllegalAccessLogger objects.
|
|
||||||
*/
|
|
||||||
public static class Builder {
|
|
||||||
private final Mode mode;
|
|
||||||
private final PrintStream warningStream;
|
|
||||||
private final Map<Module, Set<String>> moduleToConcealedPackages;
|
|
||||||
private final Map<Module, Set<String>> moduleToExportedPackages;
|
|
||||||
private boolean complete;
|
|
||||||
|
|
||||||
private void ensureNotComplete() {
|
|
||||||
if (complete) throw new IllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a builder.
|
|
||||||
*/
|
|
||||||
public Builder(Mode mode, PrintStream warningStream) {
|
|
||||||
this.mode = mode;
|
|
||||||
this.warningStream = warningStream;
|
|
||||||
this.moduleToConcealedPackages = new HashMap<>();
|
|
||||||
this.moduleToExportedPackages = new HashMap<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adding logging of reflective-access to any member of a type in
|
|
||||||
* otherwise concealed packages.
|
|
||||||
*/
|
|
||||||
public Builder logAccessToConcealedPackages(Module m, Set<String> packages) {
|
|
||||||
ensureNotComplete();
|
|
||||||
moduleToConcealedPackages.put(m, unmodifiableSet(packages));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adding logging of reflective-access to non-public members/types in
|
|
||||||
* otherwise exported (not open) packages.
|
|
||||||
*/
|
|
||||||
public Builder logAccessToExportedPackages(Module m, Set<String> packages) {
|
|
||||||
ensureNotComplete();
|
|
||||||
moduleToExportedPackages.put(m, unmodifiableSet(packages));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds the IllegalAccessLogger and sets it as the system-wide logger.
|
|
||||||
*/
|
|
||||||
public void complete() {
|
|
||||||
Map<Module, Set<String>> map1 = unmodifiableMap(moduleToConcealedPackages);
|
|
||||||
Map<Module, Set<String>> map2 = unmodifiableMap(moduleToExportedPackages);
|
|
||||||
logger = new IllegalAccessLogger(mode, warningStream, map1, map2);
|
|
||||||
complete = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// need access to java.lang.Module
|
|
||||||
private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
|
|
||||||
|
|
||||||
// system-wide IllegalAccessLogger
|
|
||||||
private static volatile IllegalAccessLogger logger;
|
|
||||||
|
|
||||||
// logger mode
|
|
||||||
private final Mode mode;
|
|
||||||
|
|
||||||
// the print stream to send the warnings
|
|
||||||
private final PrintStream warningStream;
|
|
||||||
|
|
||||||
// module -> packages open for illegal access
|
|
||||||
private final Map<Module, Set<String>> moduleToConcealedPackages;
|
|
||||||
private final Map<Module, Set<String>> moduleToExportedPackages;
|
|
||||||
|
|
||||||
// caller -> usages
|
|
||||||
private final Map<Class<?>, Usages> callerToUsages = new WeakHashMap<>();
|
|
||||||
|
|
||||||
private IllegalAccessLogger(Mode mode,
|
|
||||||
PrintStream warningStream,
|
|
||||||
Map<Module, Set<String>> moduleToConcealedPackages,
|
|
||||||
Map<Module, Set<String>> moduleToExportedPackages)
|
|
||||||
{
|
|
||||||
this.mode = mode;
|
|
||||||
this.warningStream = warningStream;
|
|
||||||
this.moduleToConcealedPackages = moduleToConcealedPackages;
|
|
||||||
this.moduleToExportedPackages = moduleToExportedPackages;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the system-wide IllegalAccessLogger or {@code null} if there is
|
|
||||||
* no logger.
|
|
||||||
*/
|
|
||||||
public static IllegalAccessLogger illegalAccessLogger() {
|
|
||||||
return logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the module exports a concealed package for illegal
|
|
||||||
* access.
|
|
||||||
*/
|
|
||||||
public boolean isExportedForIllegalAccess(Module module, String pn) {
|
|
||||||
Set<String> packages = moduleToConcealedPackages.get(module);
|
|
||||||
if (packages != null && packages.contains(pn))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the module opens a concealed or exported package for
|
|
||||||
* illegal access.
|
|
||||||
*/
|
|
||||||
public boolean isOpenForIllegalAccess(Module module, String pn) {
|
|
||||||
if (isExportedForIllegalAccess(module, pn))
|
|
||||||
return true;
|
|
||||||
Set<String> packages = moduleToExportedPackages.get(module);
|
|
||||||
if (packages != null && packages.contains(pn))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Logs access to the member of a target class by a caller class if the class
|
|
||||||
* is in a package that is exported for illegal access.
|
|
||||||
*
|
|
||||||
* The {@code whatSupplier} supplies the message that describes the member.
|
|
||||||
*/
|
|
||||||
public void logIfExportedForIllegalAccess(Class<?> caller,
|
|
||||||
Class<?> target,
|
|
||||||
Supplier<String> whatSupplier) {
|
|
||||||
Module targetModule = target.getModule();
|
|
||||||
String targetPackage = target.getPackageName();
|
|
||||||
if (isExportedForIllegalAccess(targetModule, targetPackage)) {
|
|
||||||
Module callerModule = caller.getModule();
|
|
||||||
if (!JLA.isReflectivelyExported(targetModule, targetPackage, callerModule)) {
|
|
||||||
log(caller, whatSupplier.get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Logs access to the member of a target class by a caller class if the class
|
|
||||||
* is in a package that is opened for illegal access.
|
|
||||||
*
|
|
||||||
* The {@code what} parameter supplies the message that describes the member.
|
|
||||||
*/
|
|
||||||
public void logIfOpenedForIllegalAccess(Class<?> caller,
|
|
||||||
Class<?> target,
|
|
||||||
Supplier<String> whatSupplier) {
|
|
||||||
Module targetModule = target.getModule();
|
|
||||||
String targetPackage = target.getPackageName();
|
|
||||||
if (isOpenForIllegalAccess(targetModule, targetPackage)) {
|
|
||||||
Module callerModule = caller.getModule();
|
|
||||||
if (!JLA.isReflectivelyOpened(targetModule, targetPackage, callerModule)) {
|
|
||||||
log(caller, whatSupplier.get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Logs access by caller lookup if the target class is in a package that is
|
|
||||||
* opened for illegal access.
|
|
||||||
*/
|
|
||||||
public void logIfOpenedForIllegalAccess(MethodHandles.Lookup caller, Class<?> target) {
|
|
||||||
Module targetModule = target.getModule();
|
|
||||||
String targetPackage = target.getPackageName();
|
|
||||||
if (isOpenForIllegalAccess(targetModule, targetPackage)) {
|
|
||||||
Class<?> callerClass = caller.lookupClass();
|
|
||||||
Module callerModule = callerClass.getModule();
|
|
||||||
if (!JLA.isReflectivelyOpened(targetModule, targetPackage, callerModule)) {
|
|
||||||
URL url = codeSource(callerClass);
|
|
||||||
final String source;
|
|
||||||
if (url == null) {
|
|
||||||
source = callerClass.getName();
|
|
||||||
} else {
|
|
||||||
source = callerClass.getName() + " (" + url + ")";
|
|
||||||
}
|
|
||||||
log(callerClass, target.getName(), () ->
|
|
||||||
"WARNING: Illegal reflective access using Lookup on " + source
|
|
||||||
+ " to " + target);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Logs access by a caller class. The {@code what} parameter describes
|
|
||||||
* the member being accessed.
|
|
||||||
*/
|
|
||||||
private void log(Class<?> caller, String what) {
|
|
||||||
log(caller, what, () -> {
|
|
||||||
URL url = codeSource(caller);
|
|
||||||
String source = caller.getName();
|
|
||||||
if (url != null)
|
|
||||||
source += " (" + url + ")";
|
|
||||||
return "WARNING: Illegal reflective access by " + source + " to " + what;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Log access by a caller. The {@code what} parameter describes the class or
|
|
||||||
* member that is being accessed. The {@code msgSupplier} supplies the log
|
|
||||||
* message.
|
|
||||||
*
|
|
||||||
* To reduce output, this method only logs the access if it hasn't been seen
|
|
||||||
* previously. "Seen previously" is implemented as a map of caller class -> Usage,
|
|
||||||
* where a Usage is the "what" and a hash of the stack trace. The map has weak
|
|
||||||
* keys so it can be expunged when the caller is GC'ed/unloaded.
|
|
||||||
*/
|
|
||||||
private void log(Class<?> caller, String what, Supplier<String> msgSupplier) {
|
|
||||||
if (mode == Mode.ONESHOT) {
|
|
||||||
synchronized (IllegalAccessLogger.class) {
|
|
||||||
// discard the system wide logger
|
|
||||||
if (logger == null)
|
|
||||||
return;
|
|
||||||
logger = null;
|
|
||||||
}
|
|
||||||
warningStream.println(loudWarning(caller, msgSupplier));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// stack trace without the top-most frames in java.base
|
|
||||||
List<StackWalker.StackFrame> stack = StackWalkerHolder.INSTANCE.walk(s ->
|
|
||||||
s.dropWhile(this::isJavaBase)
|
|
||||||
.limit(32)
|
|
||||||
.toList()
|
|
||||||
);
|
|
||||||
|
|
||||||
// record usage if this is the first (or not recently recorded)
|
|
||||||
Usage u = new Usage(what, hash(stack));
|
|
||||||
boolean added;
|
|
||||||
synchronized (this) {
|
|
||||||
added = callerToUsages.computeIfAbsent(caller, k -> new Usages()).add(u);
|
|
||||||
}
|
|
||||||
|
|
||||||
// print warning if this is the first (or not a recent) usage
|
|
||||||
if (added) {
|
|
||||||
String msg = msgSupplier.get();
|
|
||||||
if (mode == Mode.DEBUG) {
|
|
||||||
StringBuilder sb = new StringBuilder(msg);
|
|
||||||
stack.forEach(f ->
|
|
||||||
sb.append(System.lineSeparator()).append("\tat " + f)
|
|
||||||
);
|
|
||||||
msg = sb.toString();
|
|
||||||
}
|
|
||||||
warningStream.println(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the code source for the given class or null if there is no code source
|
|
||||||
*/
|
|
||||||
private URL codeSource(Class<?> clazz) {
|
|
||||||
PrivilegedAction<ProtectionDomain> pa = clazz::getProtectionDomain;
|
|
||||||
CodeSource cs = AccessController.doPrivileged(pa).getCodeSource();
|
|
||||||
return (cs != null) ? cs.getLocation() : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String loudWarning(Class<?> caller, Supplier<String> msgSupplier) {
|
|
||||||
StringJoiner sj = new StringJoiner(System.lineSeparator());
|
|
||||||
sj.add("WARNING: An illegal reflective access operation has occurred");
|
|
||||||
sj.add(msgSupplier.get());
|
|
||||||
sj.add("WARNING: Please consider reporting this to the maintainers of "
|
|
||||||
+ caller.getName());
|
|
||||||
sj.add("WARNING: Use --illegal-access=warn to enable warnings of further"
|
|
||||||
+ " illegal reflective access operations");
|
|
||||||
sj.add("WARNING: All illegal access operations will be denied in a"
|
|
||||||
+ " future release");
|
|
||||||
return sj.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class StackWalkerHolder {
|
|
||||||
static final StackWalker INSTANCE;
|
|
||||||
static {
|
|
||||||
PrivilegedAction<StackWalker> pa = () ->
|
|
||||||
StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
|
|
||||||
INSTANCE = AccessController.doPrivileged(pa);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the stack frame is for a class in java.base.
|
|
||||||
*/
|
|
||||||
private boolean isJavaBase(StackWalker.StackFrame frame) {
|
|
||||||
Module caller = frame.getDeclaringClass().getModule();
|
|
||||||
return "java.base".equals(caller.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Computes a hash code for the give stack frames. The hash code is based
|
|
||||||
* on the class, method name, and BCI.
|
|
||||||
*/
|
|
||||||
private int hash(List<StackWalker.StackFrame> stack) {
|
|
||||||
int hash = 0;
|
|
||||||
for (StackWalker.StackFrame frame : stack) {
|
|
||||||
hash = (31 * hash) + Objects.hash(frame.getDeclaringClass(),
|
|
||||||
frame.getMethodName(),
|
|
||||||
frame.getByteCodeIndex());
|
|
||||||
}
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class Usage {
|
|
||||||
private final String what;
|
|
||||||
private final int stack;
|
|
||||||
Usage(String what, int stack) {
|
|
||||||
this.what = what;
|
|
||||||
this.stack = stack;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return what.hashCode() ^ stack;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object ob) {
|
|
||||||
if (ob instanceof Usage) {
|
|
||||||
Usage that = (Usage)ob;
|
|
||||||
return what.equals(that.what) && stack == (that.stack);
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
|
||||||
private static class Usages extends LinkedHashMap<Usage, Boolean> {
|
|
||||||
Usages() { }
|
|
||||||
boolean add(Usage u) {
|
|
||||||
return (putIfAbsent(u, Boolean.TRUE) == null);
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
protected boolean removeEldestEntry(Map.Entry<Usage, Boolean> oldest) {
|
|
||||||
// prevent map growing too big, say where a utility class
|
|
||||||
// is used by generated code to do illegal access
|
|
||||||
return size() > 16;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,130 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2017, 2019, 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. Oracle designates this
|
|
||||||
* particular file as subject to the "Classpath" exception as provided
|
|
||||||
* by Oracle in the LICENSE file that accompanied this code.
|
|
||||||
*
|
|
||||||
* 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 jdk.internal.module;
|
|
||||||
|
|
||||||
import sun.nio.cs.UTF_8;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.io.UncheckedIOException;
|
|
||||||
import java.lang.module.ModuleDescriptor;
|
|
||||||
import java.lang.module.ModuleFinder;
|
|
||||||
import java.lang.module.ModuleReference;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates the maps of concealed and exported packages to open at run-time.
|
|
||||||
*
|
|
||||||
* This is used at run-time for exploded builds, and at link-time to generate
|
|
||||||
* the maps for the system modules in the run-time image.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class IllegalAccessMaps {
|
|
||||||
private final Map<String, Set<String>> concealedPackagesToOpen;
|
|
||||||
private final Map<String, Set<String>> exportedPackagesToOpen;
|
|
||||||
|
|
||||||
private IllegalAccessMaps(Map<String, Set<String>> map1,
|
|
||||||
Map<String, Set<String>> map2) {
|
|
||||||
this.concealedPackagesToOpen = map1;
|
|
||||||
this.exportedPackagesToOpen = map2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the map of concealed packages to open. The map key is the
|
|
||||||
* module name, the value is the set of concealed packages to open.
|
|
||||||
*/
|
|
||||||
public Map<String, Set<String>> concealedPackagesToOpen() {
|
|
||||||
return concealedPackagesToOpen;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the map of exported packages to open. The map key is the
|
|
||||||
* module name, the value is the set of exported packages to open.
|
|
||||||
*/
|
|
||||||
public Map<String, Set<String>> exportedPackagesToOpen() {
|
|
||||||
return exportedPackagesToOpen;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate the maps of module to concealed and exported packages for
|
|
||||||
* the system modules that are observable with the given module finder.
|
|
||||||
*/
|
|
||||||
public static IllegalAccessMaps generate(ModuleFinder finder) {
|
|
||||||
Map<String, ModuleDescriptor> map = new HashMap<>();
|
|
||||||
finder.findAll().stream()
|
|
||||||
.map(ModuleReference::descriptor)
|
|
||||||
.forEach(md -> md.packages().forEach(pn -> map.putIfAbsent(pn, md)));
|
|
||||||
|
|
||||||
Map<String, Set<String>> concealedPackagesToOpen = new HashMap<>();
|
|
||||||
Map<String, Set<String>> exportedPackagesToOpen = new HashMap<>();
|
|
||||||
|
|
||||||
String rn = "jdk8_packages.dat";
|
|
||||||
InputStream in = IllegalAccessMaps.class.getResourceAsStream(rn);
|
|
||||||
if (in == null) {
|
|
||||||
throw new InternalError(rn + " not found");
|
|
||||||
}
|
|
||||||
try (BufferedReader br = new BufferedReader(
|
|
||||||
new InputStreamReader(in, UTF_8.INSTANCE)))
|
|
||||||
{
|
|
||||||
br.lines()
|
|
||||||
.filter(line -> !line.isEmpty() && !line.startsWith("#"))
|
|
||||||
.forEach(pn -> {
|
|
||||||
ModuleDescriptor descriptor = map.get(pn);
|
|
||||||
if (descriptor != null && !isOpen(descriptor, pn)) {
|
|
||||||
String name = descriptor.name();
|
|
||||||
if (isExported(descriptor, pn)) {
|
|
||||||
exportedPackagesToOpen.computeIfAbsent(name,
|
|
||||||
k -> new HashSet<>()).add(pn);
|
|
||||||
} else {
|
|
||||||
concealedPackagesToOpen.computeIfAbsent(name,
|
|
||||||
k -> new HashSet<>()).add(pn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
throw new UncheckedIOException(ioe);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new IllegalAccessMaps(concealedPackagesToOpen, exportedPackagesToOpen);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isExported(ModuleDescriptor descriptor, String pn) {
|
|
||||||
return descriptor.exports()
|
|
||||||
.stream()
|
|
||||||
.anyMatch(e -> e.source().equals(pn) && !e.isQualified());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isOpen(ModuleDescriptor descriptor, String pn) {
|
|
||||||
return descriptor.opens()
|
|
||||||
.stream()
|
|
||||||
.anyMatch(e -> e.source().equals(pn) && !e.isQualified());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -38,7 +38,6 @@ import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -147,8 +146,7 @@ public final class ModuleBootstrap {
|
||||||
getProperty("jdk.module.limitmods") == null && // --limit-modules
|
getProperty("jdk.module.limitmods") == null && // --limit-modules
|
||||||
getProperty("jdk.module.addreads.0") == null && // --add-reads
|
getProperty("jdk.module.addreads.0") == null && // --add-reads
|
||||||
getProperty("jdk.module.addexports.0") == null && // --add-exports
|
getProperty("jdk.module.addexports.0") == null && // --add-exports
|
||||||
getProperty("jdk.module.addopens.0") == null && // --add-opens
|
getProperty("jdk.module.addopens.0") == null; // --add-opens
|
||||||
getProperty("jdk.module.illegalAccess") == null; // --illegal-access
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -189,7 +187,6 @@ public final class ModuleBootstrap {
|
||||||
String mainModule = System.getProperty("jdk.module.main");
|
String mainModule = System.getProperty("jdk.module.main");
|
||||||
Set<String> addModules = addModules();
|
Set<String> addModules = addModules();
|
||||||
Set<String> limitModules = limitModules();
|
Set<String> limitModules = limitModules();
|
||||||
String illegalAccess = getAndRemoveProperty("jdk.module.illegalAccess");
|
|
||||||
|
|
||||||
PrintStream traceOutput = null;
|
PrintStream traceOutput = null;
|
||||||
String trace = getAndRemoveProperty("jdk.module.showModuleResolution");
|
String trace = getAndRemoveProperty("jdk.module.showModuleResolution");
|
||||||
|
@ -221,8 +218,7 @@ public final class ModuleBootstrap {
|
||||||
&& !haveModulePath
|
&& !haveModulePath
|
||||||
&& addModules.isEmpty()
|
&& addModules.isEmpty()
|
||||||
&& limitModules.isEmpty()
|
&& limitModules.isEmpty()
|
||||||
&& !isPatched
|
&& !isPatched) {
|
||||||
&& illegalAccess == null) {
|
|
||||||
systemModuleFinder = archivedModuleGraph.finder();
|
systemModuleFinder = archivedModuleGraph.finder();
|
||||||
hasSplitPackages = archivedModuleGraph.hasSplitPackages();
|
hasSplitPackages = archivedModuleGraph.hasSplitPackages();
|
||||||
hasIncubatorModules = archivedModuleGraph.hasIncubatorModules();
|
hasIncubatorModules = archivedModuleGraph.hasIncubatorModules();
|
||||||
|
@ -455,19 +451,10 @@ public final class ModuleBootstrap {
|
||||||
checkIncubatingStatus(cf);
|
checkIncubatingStatus(cf);
|
||||||
}
|
}
|
||||||
|
|
||||||
// --add-reads, --add-exports/--add-opens, and --illegal-access
|
// --add-reads, --add-exports/--add-opens
|
||||||
addExtraReads(bootLayer);
|
addExtraReads(bootLayer);
|
||||||
boolean extraExportsOrOpens = addExtraExportsAndOpens(bootLayer);
|
boolean extraExportsOrOpens = addExtraExportsAndOpens(bootLayer);
|
||||||
|
|
||||||
if (illegalAccess != null) {
|
|
||||||
assert systemModules != null;
|
|
||||||
addIllegalAccess(illegalAccess,
|
|
||||||
systemModules,
|
|
||||||
upgradeModulePath,
|
|
||||||
bootLayer,
|
|
||||||
extraExportsOrOpens);
|
|
||||||
}
|
|
||||||
|
|
||||||
Counters.add("jdk.module.boot.7.adjustModulesTime");
|
Counters.add("jdk.module.boot.7.adjustModulesTime");
|
||||||
|
|
||||||
// save module finders for later use
|
// save module finders for later use
|
||||||
|
@ -779,96 +766,6 @@ public final class ModuleBootstrap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Process the --illegal-access option to open packages of system modules
|
|
||||||
* in the boot layer to code in unnamed modules.
|
|
||||||
*/
|
|
||||||
private static void addIllegalAccess(String illegalAccess,
|
|
||||||
SystemModules systemModules,
|
|
||||||
ModuleFinder upgradeModulePath,
|
|
||||||
ModuleLayer bootLayer,
|
|
||||||
boolean extraExportsOrOpens) {
|
|
||||||
|
|
||||||
if (illegalAccess.equals("deny"))
|
|
||||||
return; // nothing to do
|
|
||||||
|
|
||||||
IllegalAccessLogger.Mode mode = switch (illegalAccess) {
|
|
||||||
case "permit" -> IllegalAccessLogger.Mode.ONESHOT;
|
|
||||||
case "warn" -> IllegalAccessLogger.Mode.WARN;
|
|
||||||
case "debug" -> IllegalAccessLogger.Mode.DEBUG;
|
|
||||||
default -> {
|
|
||||||
fail("Value specified to --illegal-access not recognized:"
|
|
||||||
+ " '" + illegalAccess + "'");
|
|
||||||
yield null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var builder = new IllegalAccessLogger.Builder(mode, System.err);
|
|
||||||
Map<String, Set<String>> concealedPackagesToOpen = systemModules.concealedPackagesToOpen();
|
|
||||||
Map<String, Set<String>> exportedPackagesToOpen = systemModules.exportedPackagesToOpen();
|
|
||||||
if (concealedPackagesToOpen.isEmpty() && exportedPackagesToOpen.isEmpty()) {
|
|
||||||
// need to generate (exploded build)
|
|
||||||
IllegalAccessMaps maps = IllegalAccessMaps.generate(limitedFinder());
|
|
||||||
concealedPackagesToOpen = maps.concealedPackagesToOpen();
|
|
||||||
exportedPackagesToOpen = maps.exportedPackagesToOpen();
|
|
||||||
}
|
|
||||||
|
|
||||||
// open specific packages in the system modules
|
|
||||||
Set<String> emptySet = Set.of();
|
|
||||||
for (Module m : bootLayer.modules()) {
|
|
||||||
ModuleDescriptor descriptor = m.getDescriptor();
|
|
||||||
String name = m.getName();
|
|
||||||
|
|
||||||
// skip open modules
|
|
||||||
if (descriptor.isOpen()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// skip modules loaded from the upgrade module path
|
|
||||||
if (upgradeModulePath != null
|
|
||||||
&& upgradeModulePath.find(name).isPresent()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Set<String> concealedPackages = concealedPackagesToOpen.getOrDefault(name, emptySet);
|
|
||||||
Set<String> exportedPackages = exportedPackagesToOpen.getOrDefault(name, emptySet);
|
|
||||||
|
|
||||||
// refresh the set of concealed and exported packages if needed
|
|
||||||
if (extraExportsOrOpens) {
|
|
||||||
concealedPackages = new HashSet<>(concealedPackages);
|
|
||||||
exportedPackages = new HashSet<>(exportedPackages);
|
|
||||||
Iterator<String> iterator = concealedPackages.iterator();
|
|
||||||
while (iterator.hasNext()) {
|
|
||||||
String pn = iterator.next();
|
|
||||||
if (m.isExported(pn, BootLoader.getUnnamedModule())) {
|
|
||||||
// concealed package is exported to ALL-UNNAMED
|
|
||||||
iterator.remove();
|
|
||||||
exportedPackages.add(pn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
iterator = exportedPackages.iterator();
|
|
||||||
while (iterator.hasNext()) {
|
|
||||||
String pn = iterator.next();
|
|
||||||
if (m.isOpen(pn, BootLoader.getUnnamedModule())) {
|
|
||||||
// exported package is opened to ALL-UNNAMED
|
|
||||||
iterator.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// log reflective access to all types in concealed packages
|
|
||||||
builder.logAccessToConcealedPackages(m, concealedPackages);
|
|
||||||
|
|
||||||
// log reflective access to non-public members/types in exported packages
|
|
||||||
builder.logAccessToExportedPackages(m, exportedPackages);
|
|
||||||
|
|
||||||
// open the packages to unnamed modules
|
|
||||||
JLA.addOpensToAllUnnamed(m, concealedPackages, exportedPackages);
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.complete();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decodes the values of --add-reads, -add-exports, --add-opens or
|
* Decodes the values of --add-reads, -add-exports, --add-opens or
|
||||||
* --patch-modules options that are encoded in system properties.
|
* --patch-modules options that are encoded in system properties.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -83,16 +83,4 @@ interface SystemModules {
|
||||||
* by this SystemModules object.
|
* by this SystemModules object.
|
||||||
*/
|
*/
|
||||||
Map<String, Set<String>> moduleReads();
|
Map<String, Set<String>> moduleReads();
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the map of module concealed packages to open. The map key is the
|
|
||||||
* module name, the value is the set of concealed packages to open.
|
|
||||||
*/
|
|
||||||
Map<String, Set<String>> concealedPackagesToOpen();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the map of module exported packages to open. The map key is the
|
|
||||||
* module name, the value is the set of exported packages to open.
|
|
||||||
*/
|
|
||||||
Map<String, Set<String>> exportedPackagesToOpen();
|
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,5 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved.
|
# Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
#
|
#
|
||||||
# This code is free software; you can redistribute it and/or modify it
|
# This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -185,11 +185,6 @@ java.launcher.X.usage=\n\
|
||||||
\ --add-opens <module>/<package>=<target-module>(,<target-module>)*\n\
|
\ --add-opens <module>/<package>=<target-module>(,<target-module>)*\n\
|
||||||
\ updates <module> to open <package> to\n\
|
\ updates <module> to open <package> to\n\
|
||||||
\ <target-module>, regardless of module declaration.\n\
|
\ <target-module>, regardless of module declaration.\n\
|
||||||
\ --illegal-access=<value>\n\
|
|
||||||
\ permit or deny access to members of types in named modules\n\
|
|
||||||
\ by code in unnamed modules.\n\
|
|
||||||
\ <value> is one of "deny", "permit", "warn", or "debug"\n\
|
|
||||||
\ This option will be removed in a future release.\n\
|
|
||||||
\ --limit-modules <module name>[,<module name>...]\n\
|
\ --limit-modules <module name>[,<module name>...]\n\
|
||||||
\ limit the universe of observable modules\n\
|
\ limit the universe of observable modules\n\
|
||||||
\ --patch-module <module>=<file>({0}<file>)*\n\
|
\ --patch-module <module>=<file>({0}<file>)*\n\
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -60,7 +60,6 @@ import java.util.stream.Collectors;
|
||||||
|
|
||||||
import jdk.internal.module.Checks;
|
import jdk.internal.module.Checks;
|
||||||
import jdk.internal.module.DefaultRoots;
|
import jdk.internal.module.DefaultRoots;
|
||||||
import jdk.internal.module.IllegalAccessMaps;
|
|
||||||
import jdk.internal.module.Modules;
|
import jdk.internal.module.Modules;
|
||||||
import jdk.internal.module.ModuleHashes;
|
import jdk.internal.module.ModuleHashes;
|
||||||
import jdk.internal.module.ModuleInfo.Attributes;
|
import jdk.internal.module.ModuleInfo.Attributes;
|
||||||
|
@ -622,9 +621,6 @@ public final class SystemModulesPlugin extends AbstractPlugin {
|
||||||
// generate moduleReads
|
// generate moduleReads
|
||||||
genModuleReads(cw, cf);
|
genModuleReads(cw, cf);
|
||||||
|
|
||||||
// generate concealedPackagesToOpen and exportedPackagesToOpen
|
|
||||||
genXXXPackagesToOpenMethods(cw);
|
|
||||||
|
|
||||||
return cw;
|
return cw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -855,16 +851,6 @@ public final class SystemModulesPlugin extends AbstractPlugin {
|
||||||
generate(cw, "moduleReads", map, true);
|
generate(cw, "moduleReads", map, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate concealedPackagesToOpen and exportedPackagesToOpen methods.
|
|
||||||
*/
|
|
||||||
private void genXXXPackagesToOpenMethods(ClassWriter cw) {
|
|
||||||
ModuleFinder finder = finderOf(moduleInfos);
|
|
||||||
IllegalAccessMaps maps = IllegalAccessMaps.generate(finder);
|
|
||||||
generate(cw, "concealedPackagesToOpen", maps.concealedPackagesToOpen(), false);
|
|
||||||
generate(cw, "exportedPackagesToOpen", maps.exportedPackagesToOpen(), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate method to return {@code Map<String, Set<String>>}.
|
* Generate method to return {@code Map<String, Set<String>>}.
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -35,7 +35,7 @@ import static org.testng.Assert.*;
|
||||||
* @test
|
* @test
|
||||||
* @summary Basic test of java.lang.Module
|
* @summary Basic test of java.lang.Module
|
||||||
* @modules java.desktop java.xml
|
* @modules java.desktop java.xml
|
||||||
* @run testng/othervm --illegal-access=deny BasicModuleTest
|
* @run testng/othervm BasicModuleTest
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class BasicModuleTest {
|
public class BasicModuleTest {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -29,7 +29,7 @@
|
||||||
* java.base/jdk.internal.test.TestProviderImpl1
|
* java.base/jdk.internal.test.TestProviderImpl1
|
||||||
* java.base/jdk.internal.test.TestProviderImpl2
|
* java.base/jdk.internal.test.TestProviderImpl2
|
||||||
* @run shell MakeJAR3.sh RedefineModuleAgent
|
* @run shell MakeJAR3.sh RedefineModuleAgent
|
||||||
* @run testng/othervm --illegal-access=deny -javaagent:RedefineModuleAgent.jar RedefineModuleTest
|
* @run testng/othervm -javaagent:RedefineModuleAgent.jar RedefineModuleTest
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.lang.TestProvider;
|
import java.lang.TestProvider;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -24,7 +24,7 @@
|
||||||
/* @test
|
/* @test
|
||||||
* @bug 8196830 8235351
|
* @bug 8196830 8235351
|
||||||
* @modules java.base/jdk.internal.reflect
|
* @modules java.base/jdk.internal.reflect
|
||||||
* @run testng/othervm --illegal-access=deny CallerSensitiveAccess
|
* @run testng/othervm CallerSensitiveAccess
|
||||||
* @summary Check Lookup findVirtual, findStatic and unreflect behavior with
|
* @summary Check Lookup findVirtual, findStatic and unreflect behavior with
|
||||||
* caller sensitive methods with focus on AccessibleObject.setAccessible
|
* caller sensitive methods with focus on AccessibleObject.setAccessible
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -25,7 +25,7 @@
|
||||||
* @test
|
* @test
|
||||||
* @build CanAccessTest
|
* @build CanAccessTest
|
||||||
* @modules java.base/jdk.internal.misc:+open
|
* @modules java.base/jdk.internal.misc:+open
|
||||||
* @run testng/othervm --illegal-access=deny CanAccessTest
|
* @run testng/othervm CanAccessTest
|
||||||
* @summary Test AccessibleObject::canAccess method
|
* @summary Test AccessibleObject::canAccess method
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
* @build ModuleSetAccessibleTest
|
* @build ModuleSetAccessibleTest
|
||||||
* @modules java.base/java.lang:open
|
* @modules java.base/java.lang:open
|
||||||
* java.base/jdk.internal.misc:+open
|
* java.base/jdk.internal.misc:+open
|
||||||
* @run testng/othervm --illegal-access=deny ModuleSetAccessibleTest
|
* @run testng/othervm ModuleSetAccessibleTest
|
||||||
* @summary Test java.lang.reflect.AccessibleObject with modules
|
* @summary Test java.lang.reflect.AccessibleObject with modules
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -28,7 +28,7 @@
|
||||||
* java.base/jdk.internal.module
|
* java.base/jdk.internal.module
|
||||||
* java.base/jdk.internal.perf
|
* java.base/jdk.internal.perf
|
||||||
* java.base/jdk.internal.misc:+open
|
* java.base/jdk.internal.misc:+open
|
||||||
* @run testng/othervm --illegal-access=deny TrySetAccessibleTest
|
* @run testng/othervm TrySetAccessibleTest
|
||||||
* @summary Test AccessibleObject::trySetAccessible method
|
* @summary Test AccessibleObject::trySetAccessible method
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -87,7 +87,6 @@ public class CacheTest {
|
||||||
assertTrue(executeTestJava("--class-path", MODS_DIR.resolve(TEST_MODULE).toString(),
|
assertTrue(executeTestJava("--class-path", MODS_DIR.resolve(TEST_MODULE).toString(),
|
||||||
"--module-path", MODS_DIR.resolve(MAIN_BUNDLES_MODULE).toString(),
|
"--module-path", MODS_DIR.resolve(MAIN_BUNDLES_MODULE).toString(),
|
||||||
"--add-modules", MAIN_BUNDLES_MODULE,
|
"--add-modules", MAIN_BUNDLES_MODULE,
|
||||||
"--illegal-access=deny",
|
|
||||||
MAIN_CLASS, "cache")
|
MAIN_CLASS, "cache")
|
||||||
.outputTo(System.out)
|
.outputTo(System.out)
|
||||||
.errorTo(System.out)
|
.errorTo(System.out)
|
||||||
|
@ -110,7 +109,6 @@ public class CacheTest {
|
||||||
assertTrue(executeTestJava("--class-path", MODS_DIR.resolve(TEST_MODULE).toString(),
|
assertTrue(executeTestJava("--class-path", MODS_DIR.resolve(TEST_MODULE).toString(),
|
||||||
"--module-path", MODS_DIR.resolve(MAIN_BUNDLES_MODULE).toString(),
|
"--module-path", MODS_DIR.resolve(MAIN_BUNDLES_MODULE).toString(),
|
||||||
"--add-modules", MAIN_BUNDLES_MODULE,
|
"--add-modules", MAIN_BUNDLES_MODULE,
|
||||||
"--illegal-access=deny",
|
|
||||||
MAIN_CLASS)
|
MAIN_CLASS)
|
||||||
.outputTo(System.out)
|
.outputTo(System.out)
|
||||||
.errorTo(System.out)
|
.errorTo(System.out)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -25,7 +25,7 @@
|
||||||
* @test
|
* @test
|
||||||
* @library modules
|
* @library modules
|
||||||
* @build m1/* m2/*
|
* @build m1/* m2/*
|
||||||
* @run testng/othervm --add-modules=m1,m2 --illegal-access=deny Basic
|
* @run testng/othervm --add-modules=m1,m2 Basic
|
||||||
* @summary Basic test of open modules and open packages
|
* @summary Basic test of open modules and open packages
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -88,8 +88,7 @@ public class AddExportsAndOpensInManifest {
|
||||||
Paths.get("Test1.class"), Paths.get("Test2.class"));
|
Paths.get("Test1.class"), Paths.get("Test2.class"));
|
||||||
|
|
||||||
// java -jar test.jar
|
// java -jar test.jar
|
||||||
return ProcessTools.executeTestJava("--illegal-access=deny",
|
return ProcessTools.executeTestJava("-jar", jarfile.toString())
|
||||||
"-jar", jarfile.toString())
|
|
||||||
.outputTo(System.out)
|
.outputTo(System.out)
|
||||||
.errorTo(System.out);
|
.errorTo(System.out);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -23,454 +23,36 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
* @requires vm.compMode != "Xcomp"
|
* @bug 8266851
|
||||||
* @modules java.base/jdk.internal.misc
|
* @library /test/lib
|
||||||
* java.base/sun.security.x509
|
* @build IllegalAccessTest
|
||||||
* @library /test/lib modules
|
* @run testng IllegalAccessTest
|
||||||
* @build IllegalAccessTest TryAccess
|
* @summary Make sure that --illegal-access=$VALUE is obsolete.
|
||||||
* jdk.test.lib.compiler.CompilerUtils
|
|
||||||
* jdk.test.lib.util.JarUtils
|
|
||||||
* @build m/*
|
|
||||||
* @run testng/othervm/timeout=180 IllegalAccessTest
|
|
||||||
* @summary Basic test for java --illegal-access=$VALUE
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.nio.file.Files;
|
import jdk.test.lib.process.*;
|
||||||
import java.nio.file.Path;
|
import org.testng.annotations.*;
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.jar.Attributes;
|
|
||||||
import java.util.jar.Manifest;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import jdk.test.lib.compiler.CompilerUtils;
|
|
||||||
import jdk.test.lib.process.ProcessTools;
|
|
||||||
import jdk.test.lib.process.OutputAnalyzer;
|
|
||||||
import jdk.test.lib.util.JarUtils;
|
|
||||||
|
|
||||||
import org.testng.annotations.DataProvider;
|
|
||||||
import org.testng.annotations.Test;
|
|
||||||
import static org.testng.Assert.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Basic test of --illegal-access=value to deny or permit access to JDK internals.
|
* Make sure that --illegal-access=$VALUE is obsolete.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public class IllegalAccessTest {
|
public class IllegalAccessTest {
|
||||||
|
|
||||||
static final String TEST_SRC = System.getProperty("test.src");
|
void run(String text, String... vmopts)
|
||||||
static final String TEST_CLASSES = System.getProperty("test.classes");
|
|
||||||
static final String MODULE_PATH = System.getProperty("jdk.module.path");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents the expected result of a test.
|
|
||||||
*/
|
|
||||||
static final class Result {
|
|
||||||
private final boolean success;
|
|
||||||
private final List<String> expectedOutput = new ArrayList<>();
|
|
||||||
private final List<String> notExpectedOutput = new ArrayList<>();
|
|
||||||
|
|
||||||
Result(boolean success) {
|
|
||||||
this.success = success;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result expect(String msg) {
|
|
||||||
expectedOutput.add(msg);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result doNotExpect(String msg) {
|
|
||||||
notExpectedOutput.add(msg);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean shouldSucceed() {
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
Stream<String> expectedOutput() {
|
|
||||||
return expectedOutput.stream();
|
|
||||||
}
|
|
||||||
|
|
||||||
Stream<String> notExpectedOutput() {
|
|
||||||
return notExpectedOutput.stream();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
String s = (success) ? "success" : "failure";
|
|
||||||
for (String msg : expectedOutput) {
|
|
||||||
s += "/" + msg;
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Result success() {
|
|
||||||
return new Result(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Result successNoWarning() {
|
|
||||||
return success().doNotExpect("WARNING");
|
|
||||||
}
|
|
||||||
|
|
||||||
static Result successWithWarning() {
|
|
||||||
return success().expect("WARNING");
|
|
||||||
}
|
|
||||||
|
|
||||||
static Result fail(String expectedOutput) {
|
|
||||||
return new Result(false).expect(expectedOutput).doNotExpect("WARNING");
|
|
||||||
}
|
|
||||||
|
|
||||||
@DataProvider(name = "denyCases")
|
|
||||||
public Object[][] denyCases() {
|
|
||||||
return new Object[][] {
|
|
||||||
{ "accessPublicClassNonExportedPackage", fail("IllegalAccessError") },
|
|
||||||
{ "accessPublicClassJdk9NonExportedPackage", fail("IllegalAccessError") },
|
|
||||||
|
|
||||||
{ "reflectPublicMemberExportedPackage", successNoWarning() },
|
|
||||||
{ "reflectNonPublicMemberExportedPackage", fail("IllegalAccessException") },
|
|
||||||
{ "reflectPublicMemberNonExportedPackage", fail("IllegalAccessException") },
|
|
||||||
{ "reflectNonPublicMemberNonExportedPackage", fail("IllegalAccessException") },
|
|
||||||
{ "reflectPublicMemberJdk9NonExportedPackage", fail("IllegalAccessException") },
|
|
||||||
{ "reflectPublicMemberApplicationModule", successNoWarning() },
|
|
||||||
|
|
||||||
{ "setAccessiblePublicMemberExportedPackage", successNoWarning() },
|
|
||||||
{ "setAccessibleNonPublicMemberExportedPackage", fail("InaccessibleObjectException") },
|
|
||||||
{ "setAccessiblePublicMemberNonExportedPackage", fail("InaccessibleObjectException") },
|
|
||||||
{ "setAccessibleNonPublicMemberNonExportedPackage", fail("InaccessibleObjectException") },
|
|
||||||
{ "setAccessiblePublicMemberJdk9NonExportedPackage", fail("InaccessibleObjectException") },
|
|
||||||
{ "setAccessiblePublicMemberApplicationModule", successNoWarning() },
|
|
||||||
{ "setAccessibleNotPublicMemberApplicationModule", fail("InaccessibleObjectException") },
|
|
||||||
|
|
||||||
{ "privateLookupPublicClassExportedPackage", fail("IllegalAccessException") },
|
|
||||||
{ "privateLookupNonPublicClassExportedPackage", fail("IllegalAccessException") },
|
|
||||||
{ "privateLookupPublicClassNonExportedPackage", fail("IllegalAccessException") },
|
|
||||||
{ "privateLookupNonPublicClassNonExportedPackage", fail("IllegalAccessException") },
|
|
||||||
{ "privateLookupPublicClassJdk9NonExportedPackage", fail("IllegalAccessException") },
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@DataProvider(name = "permitCases")
|
|
||||||
public Object[][] permitCases() {
|
|
||||||
return new Object[][] {
|
|
||||||
{ "accessPublicClassNonExportedPackage", successNoWarning() },
|
|
||||||
{ "accessPublicClassJdk9NonExportedPackage", fail("IllegalAccessError") },
|
|
||||||
|
|
||||||
{ "reflectPublicMemberExportedPackage", successNoWarning() },
|
|
||||||
{ "reflectNonPublicMemberExportedPackage", fail("IllegalAccessException") },
|
|
||||||
{ "reflectPublicMemberNonExportedPackage", successWithWarning() },
|
|
||||||
{ "reflectNonPublicMemberNonExportedPackage", fail("IllegalAccessException") },
|
|
||||||
{ "reflectPublicMemberJdk9NonExportedPackage", fail("IllegalAccessException") },
|
|
||||||
|
|
||||||
{ "setAccessiblePublicMemberExportedPackage", successNoWarning()},
|
|
||||||
{ "setAccessibleNonPublicMemberExportedPackage", successWithWarning() },
|
|
||||||
{ "setAccessiblePublicMemberNonExportedPackage", successWithWarning() },
|
|
||||||
{ "setAccessibleNonPublicMemberNonExportedPackage", successWithWarning() },
|
|
||||||
{ "setAccessiblePublicMemberJdk9NonExportedPackage", fail("InaccessibleObjectException") },
|
|
||||||
{ "setAccessiblePublicMemberApplicationModule", successNoWarning() },
|
|
||||||
{ "setAccessibleNotPublicMemberApplicationModule", fail("InaccessibleObjectException") },
|
|
||||||
|
|
||||||
{ "privateLookupPublicClassExportedPackage", successWithWarning() },
|
|
||||||
{ "privateLookupNonPublicClassExportedPackage", successWithWarning() },
|
|
||||||
{ "privateLookupPublicClassNonExportedPackage", successWithWarning() },
|
|
||||||
{ "privateLookupNonPublicClassNonExportedPackage", successWithWarning() },
|
|
||||||
{ "privateLookupPublicClassJdk9NonExportedPackage", fail("IllegalAccessException") },
|
|
||||||
{ "privateLookupPublicClassApplicationModule", fail("IllegalAccessException") },
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks an expected result with the output captured by the given
|
|
||||||
* OutputAnalyzer.
|
|
||||||
*/
|
|
||||||
void checkResult(Result expectedResult, OutputAnalyzer outputAnalyzer) {
|
|
||||||
expectedResult.expectedOutput().forEach(outputAnalyzer::shouldContain);
|
|
||||||
expectedResult.notExpectedOutput().forEach(outputAnalyzer::shouldNotContain);
|
|
||||||
int exitValue = outputAnalyzer.getExitValue();
|
|
||||||
if (expectedResult.shouldSucceed()) {
|
|
||||||
assertTrue(exitValue == 0);
|
|
||||||
} else {
|
|
||||||
assertTrue(exitValue != 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs the test to execute the given test action. The VM is run with the
|
|
||||||
* given VM options and the output checked to see that it matches the
|
|
||||||
* expected result.
|
|
||||||
*/
|
|
||||||
OutputAnalyzer run(String action, Result expectedResult, String... vmopts)
|
|
||||||
throws Exception
|
throws Exception
|
||||||
{
|
{
|
||||||
Stream<String> s1 = Stream.of(vmopts);
|
var outputAnalyzer = ProcessTools
|
||||||
Stream<String> s2 = Stream.of("-p", MODULE_PATH, "--add-modules=m",
|
.executeTestJava(vmopts)
|
||||||
"-cp", TEST_CLASSES, "TryAccess", action);
|
.outputTo(System.out)
|
||||||
String[] opts = Stream.concat(s1, s2).toArray(String[]::new);
|
.errorTo(System.out);
|
||||||
OutputAnalyzer outputAnalyzer = ProcessTools
|
outputAnalyzer.shouldContain(text);
|
||||||
.executeTestJava(opts)
|
|
||||||
.outputTo(System.out)
|
|
||||||
.errorTo(System.out);
|
|
||||||
if (expectedResult != null)
|
|
||||||
checkResult(expectedResult, outputAnalyzer);
|
|
||||||
return outputAnalyzer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputAnalyzer run(String action, String... vmopts) throws Exception {
|
public void testObsolete() throws Exception {
|
||||||
return run(action, null, vmopts);
|
run("Ignoring option --illegal-access",
|
||||||
|
"--illegal-access=permit", "--version");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs an executable JAR to execute the given test action. The VM is run
|
|
||||||
* with the given VM options and the output checked to see that it matches
|
|
||||||
* the expected result.
|
|
||||||
*/
|
|
||||||
void run(Path jarFile, String action, Result expectedResult, String... vmopts)
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
Stream<String> s1 = Stream.of(vmopts);
|
|
||||||
Stream<String> s2 = Stream.of("-jar", jarFile.toString(), action);
|
|
||||||
String[] opts = Stream.concat(s1, s2).toArray(String[]::new);
|
|
||||||
checkResult(expectedResult, ProcessTools.executeTestJava(opts)
|
|
||||||
.outputTo(System.out)
|
|
||||||
.errorTo(System.out));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(dataProvider = "denyCases")
|
|
||||||
public void testDefault(String action, Result expectedResult) throws Exception {
|
|
||||||
run(action, expectedResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(dataProvider = "denyCases")
|
|
||||||
public void testDeny(String action, Result expectedResult) throws Exception {
|
|
||||||
run(action, expectedResult, "--illegal-access=deny");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(dataProvider = "permitCases")
|
|
||||||
public void testPermit(String action, Result expectedResult) throws Exception {
|
|
||||||
run(action, expectedResult, "--illegal-access=permit");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(dataProvider = "permitCases")
|
|
||||||
public void testWarn(String action, Result expectedResult) throws Exception {
|
|
||||||
run(action, expectedResult, "--illegal-access=warn");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(dataProvider = "permitCases")
|
|
||||||
public void testDebug(String action, Result expectedResult) throws Exception {
|
|
||||||
// expect stack trace with WARNING
|
|
||||||
if (expectedResult.expectedOutput().anyMatch("WARNING"::equals)) {
|
|
||||||
expectedResult.expect("TryAccess.main");
|
|
||||||
}
|
|
||||||
run(action, expectedResult, "--illegal-access=debug");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specify --add-exports to export a package
|
|
||||||
*/
|
|
||||||
public void testWithAddExportsOption() throws Exception {
|
|
||||||
// not accessible
|
|
||||||
run("reflectPublicMemberNonExportedPackage", fail("IllegalAccessException"));
|
|
||||||
|
|
||||||
// should succeed with --add-exports
|
|
||||||
run("reflectPublicMemberNonExportedPackage", successNoWarning(),
|
|
||||||
"--add-exports", "java.base/sun.security.x509=ALL-UNNAMED");
|
|
||||||
|
|
||||||
// not accessible
|
|
||||||
run("setAccessibleNonPublicMemberNonExportedPackage", fail("InaccessibleObjectException"));
|
|
||||||
|
|
||||||
// should fail as --add-exports does not open package
|
|
||||||
run("setAccessibleNonPublicMemberNonExportedPackage", fail("InaccessibleObjectException"),
|
|
||||||
"--add-exports", "java.base/sun.nio.ch=ALL-UNNAMED");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specify --add-open to open a package
|
|
||||||
*/
|
|
||||||
public void testWithAddOpensOption() throws Exception {
|
|
||||||
// not accessible
|
|
||||||
run("reflectPublicMemberNonExportedPackage", fail("IllegalAccessException"));
|
|
||||||
|
|
||||||
// should succeed with --add-opens
|
|
||||||
run("reflectPublicMemberNonExportedPackage", successNoWarning(),
|
|
||||||
"--add-opens", "java.base/sun.security.x509=ALL-UNNAMED");
|
|
||||||
|
|
||||||
// not accessible
|
|
||||||
run("setAccessibleNonPublicMemberExportedPackage", fail("InaccessibleObjectException"));
|
|
||||||
|
|
||||||
// should succeed with --add-opens
|
|
||||||
run("setAccessibleNonPublicMemberExportedPackage", successNoWarning(),
|
|
||||||
"--add-opens", "java.base/java.lang=ALL-UNNAMED");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test reflective API to export a package
|
|
||||||
*/
|
|
||||||
public void testWithReflectiveExports() throws Exception {
|
|
||||||
// compile patch for java.base
|
|
||||||
Path src = Paths.get(TEST_SRC, "patchsrc", "java.base");
|
|
||||||
Path patch = Files.createDirectories(Paths.get("patches", "java.base"));
|
|
||||||
assertTrue(CompilerUtils.compile(src, patch,
|
|
||||||
"--patch-module", "java.base=" + src));
|
|
||||||
|
|
||||||
// reflectively export, then access
|
|
||||||
run("exportNonExportedPackages,reflectPublicMemberNonExportedPackage",
|
|
||||||
successNoWarning(),
|
|
||||||
"--patch-module", "java.base=" + patch);
|
|
||||||
|
|
||||||
// access, reflectively export, access again
|
|
||||||
List<String> output = run("reflectPublicMemberNonExportedPackage,"
|
|
||||||
+ "exportNonExportedPackages,"
|
|
||||||
+ "reflectPublicMemberNonExportedPackage",
|
|
||||||
"--patch-module", "java.base="+patch,
|
|
||||||
"--illegal-access=warn").asLines();
|
|
||||||
assertTrue(count(output, "WARNING") == 1); // one warning
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test reflective API to open a package
|
|
||||||
*/
|
|
||||||
public void testWithReflectiveOpens() throws Exception {
|
|
||||||
// compile patch for java.base
|
|
||||||
Path src = Paths.get(TEST_SRC, "patchsrc", "java.base");
|
|
||||||
Path patch = Files.createDirectories(Paths.get("patches", "java.base"));
|
|
||||||
assertTrue(CompilerUtils.compile(src, patch,
|
|
||||||
"--patch-module", "java.base=" + src));
|
|
||||||
|
|
||||||
// reflectively open exported package, then access
|
|
||||||
run("openExportedPackage,setAccessibleNonPublicMemberExportedPackage",
|
|
||||||
successNoWarning(),
|
|
||||||
"--patch-module", "java.base=" + patch);
|
|
||||||
|
|
||||||
// access, reflectively open exported package, access again
|
|
||||||
List<String> output1 = run("setAccessibleNonPublicMemberExportedPackage"
|
|
||||||
+ ",openExportedPackage"
|
|
||||||
+ ",setAccessibleNonPublicMemberExportedPackage",
|
|
||||||
"--patch-module", "java.base=" + patch,
|
|
||||||
"--illegal-access=warn").asLines();
|
|
||||||
assertTrue(count(output1, "WARNING") == 1); // one warning
|
|
||||||
|
|
||||||
// reflectively open non-exported packages, then access
|
|
||||||
run("openNonExportedPackages,setAccessibleNonPublicMemberNonExportedPackage",
|
|
||||||
successNoWarning(),
|
|
||||||
"--patch-module", "java.base=" + patch);
|
|
||||||
|
|
||||||
// access, reflectively open non-exported package, access again
|
|
||||||
List<String> output2 = run("setAccessibleNonPublicMemberNonExportedPackage"
|
|
||||||
+ ",openNonExportedPackages"
|
|
||||||
+ ",setAccessibleNonPublicMemberNonExportedPackage",
|
|
||||||
"--patch-module", "java.base=" + patch,
|
|
||||||
"--illegal-access=warn").asLines();
|
|
||||||
assertTrue(count(output2, "WARNING") == 1); // one warning
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specify Add-Exports in JAR file manifest
|
|
||||||
*/
|
|
||||||
public void testWithAddExportsInManifest() throws Exception {
|
|
||||||
Manifest man = new Manifest();
|
|
||||||
Attributes attrs = man.getMainAttributes();
|
|
||||||
attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0");
|
|
||||||
attrs.put(Attributes.Name.MAIN_CLASS, "TryAccess");
|
|
||||||
attrs.put(new Attributes.Name("Add-Exports"),
|
|
||||||
"java.base/sun.security.x509 java.base/sun.nio.ch");
|
|
||||||
Path jarfile = Paths.get("x.jar");
|
|
||||||
Path classes = Paths.get(TEST_CLASSES);
|
|
||||||
JarUtils.createJarFile(jarfile, man, classes, Paths.get("TryAccess.class"));
|
|
||||||
|
|
||||||
run(jarfile, "reflectPublicMemberNonExportedPackage", successNoWarning());
|
|
||||||
|
|
||||||
run(jarfile, "reflectPublicMemberNonExportedPackage", successNoWarning(),
|
|
||||||
"--illegal-access=permit");
|
|
||||||
|
|
||||||
// should fail as Add-Exports does not open package
|
|
||||||
run(jarfile, "setAccessibleNonPublicMemberNonExportedPackage",
|
|
||||||
fail("InaccessibleObjectException"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specify Add-Opens in JAR file manifest
|
|
||||||
*/
|
|
||||||
public void testWithAddOpensInManifest() throws Exception {
|
|
||||||
Manifest man = new Manifest();
|
|
||||||
Attributes attrs = man.getMainAttributes();
|
|
||||||
attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0");
|
|
||||||
attrs.put(Attributes.Name.MAIN_CLASS, "TryAccess");
|
|
||||||
attrs.put(new Attributes.Name("Add-Opens"), "java.base/java.lang");
|
|
||||||
Path jarfile = Paths.get("x.jar");
|
|
||||||
Path classes = Paths.get(TEST_CLASSES);
|
|
||||||
JarUtils.createJarFile(jarfile, man, classes, Paths.get("TryAccess.class"));
|
|
||||||
|
|
||||||
run(jarfile, "setAccessibleNonPublicMemberExportedPackage", successNoWarning());
|
|
||||||
|
|
||||||
run(jarfile, "setAccessibleNonPublicMemberExportedPackage", successNoWarning(),
|
|
||||||
"--illegal-access=permit");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that --illegal-access=permit behavior is to print a warning on the
|
|
||||||
* first illegal access only.
|
|
||||||
*/
|
|
||||||
public void testWarnOnFirstIllegalAccess() throws Exception {
|
|
||||||
String action1 = "reflectPublicMemberNonExportedPackage";
|
|
||||||
String action2 = "setAccessibleNonPublicMemberExportedPackage";
|
|
||||||
int warningCount = count(run(action1, "--illegal-access=permit").asLines(), "WARNING");
|
|
||||||
assertTrue(warningCount > 0); // multi line warning
|
|
||||||
|
|
||||||
// same illegal access
|
|
||||||
List<String> output1 = run(action1 + "," + action1, "--illegal-access=permit").asLines();
|
|
||||||
assertTrue(count(output1, "WARNING") == warningCount);
|
|
||||||
|
|
||||||
// different illegal access
|
|
||||||
List<String> output2 = run(action1 + "," + action2, "--illegal-access=permit").asLines();
|
|
||||||
assertTrue(count(output2, "WARNING") == warningCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that --illegal-access=warn prints a one-line warning per each unique
|
|
||||||
* illegal access.
|
|
||||||
*/
|
|
||||||
public void testWarnPerIllegalAccess() throws Exception {
|
|
||||||
String action1 = "reflectPublicMemberNonExportedPackage";
|
|
||||||
String action2 = "setAccessibleNonPublicMemberExportedPackage";
|
|
||||||
|
|
||||||
// same illegal access
|
|
||||||
String repeatedActions = action1 + "," + action1;
|
|
||||||
List<String> output1 = run(repeatedActions, "--illegal-access=warn").asLines();
|
|
||||||
assertTrue(count(output1, "WARNING") == 1);
|
|
||||||
|
|
||||||
// different illegal access
|
|
||||||
String differentActions = action1 + "," + action2;
|
|
||||||
List<String> output2 = run(differentActions, "--illegal-access=warn").asLines();
|
|
||||||
assertTrue(count(output2, "WARNING") == 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specify --illegal-access more than once, last one wins
|
|
||||||
*/
|
|
||||||
public void testRepeatedOption() throws Exception {
|
|
||||||
run("accessPublicClassNonExportedPackage", successNoWarning(),
|
|
||||||
"--illegal-access=deny", "--illegal-access=permit");
|
|
||||||
run("accessPublicClassNonExportedPackage", fail("IllegalAccessError"),
|
|
||||||
"--illegal-access=permit", "--illegal-access=deny");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specify bad value to --illegal-access
|
|
||||||
*/
|
|
||||||
public void testBadValue() throws Exception {
|
|
||||||
run("accessPublicClassNonExportedPackage",
|
|
||||||
fail("Value specified to --illegal-access not recognized"),
|
|
||||||
"--illegal-access=BAD");
|
|
||||||
}
|
|
||||||
|
|
||||||
private int count(Iterable<String> lines, CharSequence cs) {
|
|
||||||
int count = 0;
|
|
||||||
for (String line : lines) {
|
|
||||||
if (line.contains(cs)) count++;
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,188 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2017, 2018, 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandles;
|
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.nio.channels.SocketChannel;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Launched by IllegalAccessTest to attempt illegal access.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class TryAccess {
|
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
|
||||||
String[] methodNames = args[0].split(",");
|
|
||||||
for (String methodName : methodNames) {
|
|
||||||
Method m = TryAccess.class.getDeclaredMethod(methodName);
|
|
||||||
m.invoke(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// -- static access --
|
|
||||||
|
|
||||||
static void accessPublicClassNonExportedPackage() throws Exception {
|
|
||||||
Object obj = new sun.security.x509.X500Name("CN=name");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void accessPublicClassJdk9NonExportedPackage() {
|
|
||||||
Object obj = jdk.internal.misc.Unsafe.getUnsafe();
|
|
||||||
}
|
|
||||||
|
|
||||||
// -- reflective access --
|
|
||||||
|
|
||||||
static void reflectPublicMemberExportedPackage() throws Exception {
|
|
||||||
Constructor<?> ctor = String.class.getConstructor(String.class);
|
|
||||||
Object name = ctor.newInstance("value");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void reflectNonPublicMemberExportedPackage() throws Exception {
|
|
||||||
Field f = String.class.getDeclaredField("value");
|
|
||||||
Object obj = f.get("foo");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void reflectPublicMemberNonExportedPackage() throws Exception {
|
|
||||||
Class<?> clazz = Class.forName("sun.security.x509.X500Name");
|
|
||||||
Constructor<?> ctor = clazz.getConstructor(String.class);
|
|
||||||
Object obj = ctor.newInstance("CN=user");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void reflectNonPublicMemberNonExportedPackage() throws Exception {
|
|
||||||
SocketChannel sc = SocketChannel.open();
|
|
||||||
Field f = sc.getClass().getDeclaredField("fd");
|
|
||||||
Object obj = f.get(sc);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void reflectPublicMemberJdk9NonExportedPackage() throws Exception {
|
|
||||||
Class<?> clazz = Class.forName("jdk.internal.misc.Unsafe");
|
|
||||||
Method m = clazz.getMethod("getUnsafe");
|
|
||||||
Object obj = m.invoke(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void reflectPublicMemberApplicationModule() throws Exception {
|
|
||||||
Class<?> clazz = Class.forName("p.Type");
|
|
||||||
Constructor<?> ctor = clazz.getConstructor(int.class);
|
|
||||||
Object obj = ctor.newInstance(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// -- setAccessible --
|
|
||||||
|
|
||||||
static void setAccessiblePublicMemberExportedPackage() throws Exception {
|
|
||||||
Constructor<?> ctor = String.class.getConstructor(String.class);
|
|
||||||
ctor.setAccessible(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void setAccessibleNonPublicMemberExportedPackage() throws Exception {
|
|
||||||
Method method = ClassLoader.class.getDeclaredMethod("defineClass",
|
|
||||||
byte[].class, int.class, int.class);
|
|
||||||
method.setAccessible(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void setAccessiblePublicMemberNonExportedPackage() throws Exception {
|
|
||||||
Class<?> clazz = Class.forName("sun.security.x509.X500Name");
|
|
||||||
Constructor<?> ctor = clazz.getConstructor(String.class);
|
|
||||||
ctor.setAccessible(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void setAccessibleNonPublicMemberNonExportedPackage() throws Exception {
|
|
||||||
SocketChannel sc = SocketChannel.open();
|
|
||||||
Field f = sc.getClass().getDeclaredField("fd");
|
|
||||||
f.setAccessible(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void setAccessiblePublicMemberJdk9NonExportedPackage() throws Exception {
|
|
||||||
Class<?> clazz = Class.forName("jdk.internal.misc.Unsafe");
|
|
||||||
Method m = clazz.getMethod("getUnsafe");
|
|
||||||
m.setAccessible(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void setAccessiblePublicMemberApplicationModule() throws Exception {
|
|
||||||
Class<?> clazz = Class.forName("p.Type");
|
|
||||||
Constructor<?> ctor = clazz.getConstructor(int.class);
|
|
||||||
ctor.setAccessible(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void setAccessibleNotPublicMemberApplicationModule() throws Exception {
|
|
||||||
Class<?> clazz = Class.forName("p.Type");
|
|
||||||
Constructor<?> ctor = clazz.getDeclaredConstructor(int.class, int.class);
|
|
||||||
ctor.setAccessible(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// -- privateLookupIn --
|
|
||||||
|
|
||||||
static void privateLookupPublicClassExportedPackage() throws Exception {
|
|
||||||
MethodHandles.privateLookupIn(String.class, MethodHandles.lookup());
|
|
||||||
}
|
|
||||||
|
|
||||||
static void privateLookupNonPublicClassExportedPackage() throws Exception {
|
|
||||||
Class<?> clazz = Class.forName("java.lang.WeakPairMap");
|
|
||||||
MethodHandles.privateLookupIn(clazz, MethodHandles.lookup());
|
|
||||||
}
|
|
||||||
|
|
||||||
static void privateLookupPublicClassNonExportedPackage() throws Exception {
|
|
||||||
Class<?> clazz = Class.forName("sun.security.x509.X500Name");
|
|
||||||
MethodHandles.privateLookupIn(clazz, MethodHandles.lookup());
|
|
||||||
}
|
|
||||||
|
|
||||||
static void privateLookupNonPublicClassNonExportedPackage() throws Exception {
|
|
||||||
Class<?> clazz = Class.forName("sun.nio.ch.SocketChannelImpl");
|
|
||||||
MethodHandles.privateLookupIn(clazz, MethodHandles.lookup());
|
|
||||||
}
|
|
||||||
|
|
||||||
static void privateLookupPublicClassJdk9NonExportedPackage() throws Exception {
|
|
||||||
Class<?> clazz = Class.forName("jdk.internal.misc.Unsafe");
|
|
||||||
MethodHandles.privateLookupIn(clazz, MethodHandles.lookup());
|
|
||||||
}
|
|
||||||
|
|
||||||
static void privateLookupPublicClassApplicationModule() throws Exception {
|
|
||||||
Class<?> clazz = Class.forName("p.Type");
|
|
||||||
MethodHandles.privateLookupIn(clazz, MethodHandles.lookup());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// -- export/open packages to this unnamed module --
|
|
||||||
|
|
||||||
static void exportNonExportedPackages() throws Exception {
|
|
||||||
Class<?> helper = Class.forName("java.lang.Helper");
|
|
||||||
Method m = helper.getMethod("export", String.class, Module.class);
|
|
||||||
m.invoke(null, "sun.security.x509", TryAccess.class.getModule());
|
|
||||||
m.invoke(null, "sun.nio.ch", TryAccess.class.getModule());
|
|
||||||
}
|
|
||||||
|
|
||||||
static void openExportedPackage() throws Exception {
|
|
||||||
Class<?> helper = Class.forName("java.lang.Helper");
|
|
||||||
Method m = helper.getMethod("open", String.class, Module.class);
|
|
||||||
m.invoke(null, "java.lang", TryAccess.class.getModule());
|
|
||||||
}
|
|
||||||
|
|
||||||
static void openNonExportedPackages() throws Exception {
|
|
||||||
Class<?> helper = Class.forName("java.lang.Helper");
|
|
||||||
Method m = helper.getMethod("open", String.class, Module.class);
|
|
||||||
m.invoke(null, "sun.security.x509", TryAccess.class.getModule());
|
|
||||||
m.invoke(null, "sun.nio.ch", TryAccess.class.getModule());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2017, 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
module m {
|
|
||||||
exports p;
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2017, 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 p;
|
|
||||||
|
|
||||||
public class Type {
|
|
||||||
|
|
||||||
private Type(int x, int y) { }
|
|
||||||
|
|
||||||
public Type(int x) { }
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2017, 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 java.lang;
|
|
||||||
|
|
||||||
public class Helper {
|
|
||||||
private Helper() { }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Exports a package to a module.
|
|
||||||
*/
|
|
||||||
public static void export(String pn, Module other) {
|
|
||||||
Helper.class.getModule().addExports(pn, other);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Opens a package to a module.
|
|
||||||
*/
|
|
||||||
public static void open(String pn, Module other) {
|
|
||||||
Helper.class.getModule().addOpens(pn, other);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue