8301578: Perform output outside synchronization in Module.class
Reviewed-by: alanb
This commit is contained in:
parent
5830c03e53
commit
c25b4f4619
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2014, 2023, 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
|
||||||
@ -57,6 +57,7 @@ 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.Unsafe;
|
||||||
import jdk.internal.module.ModuleBootstrap;
|
import jdk.internal.module.ModuleBootstrap;
|
||||||
import jdk.internal.module.ModuleLoaderMap;
|
import jdk.internal.module.ModuleLoaderMap;
|
||||||
import jdk.internal.module.ServicesCatalog;
|
import jdk.internal.module.ServicesCatalog;
|
||||||
@ -113,6 +114,8 @@ public final class Module implements AnnotatedElement {
|
|||||||
private final ModuleDescriptor descriptor;
|
private final ModuleDescriptor descriptor;
|
||||||
|
|
||||||
// true, if this module allows restricted native access
|
// true, if this module allows restricted native access
|
||||||
|
// Accessing this variable is made through Unsafe in order to use the
|
||||||
|
// memory semantics that preserves ordering and visibility across threads.
|
||||||
@Stable
|
@Stable
|
||||||
private boolean enableNativeAccess;
|
private boolean enableNativeAccess;
|
||||||
|
|
||||||
@ -258,8 +261,8 @@ public final class Module implements AnnotatedElement {
|
|||||||
/**
|
/**
|
||||||
* Update this module to allow access to restricted methods.
|
* Update this module to allow access to restricted methods.
|
||||||
*/
|
*/
|
||||||
synchronized Module implAddEnableNativeAccess() {
|
Module implAddEnableNativeAccess() {
|
||||||
enableNativeAccess = true;
|
EnableNativeAccess.trySetEnableNativeAccess(this);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,15 +270,34 @@ public final class Module implements AnnotatedElement {
|
|||||||
* Returns {@code true} if this module can access
|
* Returns {@code true} if this module can access
|
||||||
* <a href="foreign/package-summary.html#restricted"><em>restricted</em></a> methods.
|
* <a href="foreign/package-summary.html#restricted"><em>restricted</em></a> methods.
|
||||||
*
|
*
|
||||||
* @since 20
|
|
||||||
*
|
|
||||||
* @return {@code true} if this module can access <em>restricted</em> methods.
|
* @return {@code true} if this module can access <em>restricted</em> methods.
|
||||||
|
* @since 20
|
||||||
*/
|
*/
|
||||||
@PreviewFeature(feature = PreviewFeature.Feature.FOREIGN)
|
@PreviewFeature(feature = PreviewFeature.Feature.FOREIGN)
|
||||||
public boolean isNativeAccessEnabled() {
|
public boolean isNativeAccessEnabled() {
|
||||||
Module target = moduleForNativeAccess();
|
Module target = moduleForNativeAccess();
|
||||||
synchronized(target) {
|
return EnableNativeAccess.isNativeAccessEnabled(target);
|
||||||
return target.enableNativeAccess;
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is used to be able to bootstrap without using Unsafe
|
||||||
|
* in the outer Module class as that would create a circular initializer dependency.
|
||||||
|
*/
|
||||||
|
private static final class EnableNativeAccess {
|
||||||
|
|
||||||
|
private EnableNativeAccess() {}
|
||||||
|
|
||||||
|
private static final Unsafe UNSAFE = Unsafe.getUnsafe();
|
||||||
|
private static final long FIELD_OFFSET = UNSAFE.objectFieldOffset(Module.class, "enableNativeAccess");
|
||||||
|
|
||||||
|
private static boolean isNativeAccessEnabled(Module target) {
|
||||||
|
return UNSAFE.getBooleanVolatile(target, FIELD_OFFSET);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Atomically sets enableNativeAccess if not already set
|
||||||
|
// returning if the value was updated
|
||||||
|
private static boolean trySetEnableNativeAccess(Module target) {
|
||||||
|
return UNSAFE.compareAndSetBoolean(target, FIELD_OFFSET, false, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,20 +311,11 @@ public final class Module implements AnnotatedElement {
|
|||||||
void ensureNativeAccess(Class<?> owner, String methodName) {
|
void ensureNativeAccess(Class<?> owner, String methodName) {
|
||||||
// The target module whose enableNativeAccess flag is ensured
|
// The target module whose enableNativeAccess flag is ensured
|
||||||
Module target = moduleForNativeAccess();
|
Module target = moduleForNativeAccess();
|
||||||
// racy read of the enable native access flag
|
if (!EnableNativeAccess.isNativeAccessEnabled(target)) {
|
||||||
boolean isNativeAccessEnabled = target.enableNativeAccess;
|
if (ModuleBootstrap.hasEnableNativeAccessFlag()) {
|
||||||
if (!isNativeAccessEnabled) {
|
|
||||||
synchronized (target) {
|
|
||||||
// safe read of the enableNativeAccess of the target module
|
|
||||||
isNativeAccessEnabled = target.enableNativeAccess;
|
|
||||||
|
|
||||||
// check again with the safely read flag
|
|
||||||
if (isNativeAccessEnabled) {
|
|
||||||
// another thread beat us to it - nothing to do
|
|
||||||
return;
|
|
||||||
} else if (ModuleBootstrap.hasEnableNativeAccessFlag()) {
|
|
||||||
throw new IllegalCallerException("Illegal native access from: " + this);
|
throw new IllegalCallerException("Illegal native access from: " + this);
|
||||||
} else {
|
}
|
||||||
|
if (EnableNativeAccess.trySetEnableNativeAccess(target)) {
|
||||||
// warn and set flag, so that only one warning is reported per module
|
// warn and set flag, so that only one warning is reported per module
|
||||||
String cls = owner.getName();
|
String cls = owner.getName();
|
||||||
String mtd = cls + "::" + methodName;
|
String mtd = cls + "::" + methodName;
|
||||||
@ -313,22 +326,15 @@ public final class Module implements AnnotatedElement {
|
|||||||
WARNING: %s has been called by %s
|
WARNING: %s has been called by %s
|
||||||
WARNING: Use --enable-native-access=%s to avoid a warning for this module
|
WARNING: Use --enable-native-access=%s to avoid a warning for this module
|
||||||
%n""", cls, mtd, mod, modflag);
|
%n""", cls, mtd, mod, modflag);
|
||||||
|
|
||||||
// set the flag
|
|
||||||
target.enableNativeAccess = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update all unnamed modules to allow access to restricted methods.
|
* Update all unnamed modules to allow access to restricted methods.
|
||||||
*/
|
*/
|
||||||
static void implAddEnableNativeAccessToAllUnnamed() {
|
static void implAddEnableNativeAccessToAllUnnamed() {
|
||||||
synchronized (ALL_UNNAMED_MODULE) {
|
EnableNativeAccess.trySetEnableNativeAccess(ALL_UNNAMED_MODULE);
|
||||||
ALL_UNNAMED_MODULE.enableNativeAccess = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// --
|
// --
|
||||||
|
Loading…
x
Reference in New Issue
Block a user