JDK-7103570 : AtomicIntegerFieldUpdater does not work when SecurityManager is installed
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.util.concurrent
  • Affected Version: 7
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: linux_oracle_5.4,windows_7
  • CPU: x86
  • Submitted: 2011-10-21
  • Updated: 2017-05-16
  • Resolved: 2012-05-27
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 8 Other
8 b40Fixed openjdk7uFixed
Related Reports
Duplicate :  
Description
FULL PRODUCT VERSION :
java version "1.7.0_02-ea"
Java(TM) SE Runtime Environment (build 1.7.0_02-ea-b08)
Java HotSpot(TM) Client VM (build 22.0-b06, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7601]

A DESCRIPTION OF THE PROBLEM :
The AtomicIntegerFieldUpdater and AtomicReferenceFieldUpdater classes cannot be constructed when a SecurityManager is installed. It fails with:

java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Call AtomicIntegerFieldUpdater.newUpdater when launching java with the -Djava.security.manager argument.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Expected result is a new AtomicIntegerFieldUpdater.
ACTUAL -
Actual result is a SecurityException, wrapped by a RuntimeException.

ERROR MESSAGES/STACK TRACES THAT OCCUR :
Exception in thread "main" java.lang.ExceptionInInitializerError
Caused by: java.lang.RuntimeException: java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")
        at java.util.concurrent.atomic.AtomicIntegerFieldUpdater$AtomicIntegerFieldUpdaterImpl.<init>(AtomicIntegerFieldUpdater.java:283)
        at java.util.concurrent.atomic.AtomicIntegerFieldUpdater.newUpdater(AtomicIntegerFieldUpdater.java:73)
        at dirmi.SecurityBug.<clinit>(SecurityBug.java:10)
Caused by: java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")
        at java.security.AccessControlContext.checkPermission(AccessControlContext.java:366)
        at java.security.AccessController.checkPermission(AccessController.java:555)
        at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
        at java.lang.SecurityManager.checkMemberAccess(SecurityManager.java:1679)
        at java.lang.Class.checkMemberAccess(Class.java:2174)
        at java.lang.Class.getDeclaredField(Class.java:1896)
        at java.util.concurrent.atomic.AtomicIntegerFieldUpdater$AtomicIntegerFieldUpdaterImpl.<init>(AtomicIntegerFieldUpdater.java:276)
        ... 2 more

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;

// Tests bug in AtomicIntegerFieldUpdater.
public class SecurityBug {
    private static final AtomicIntegerFieldUpdater<SecurityBug> updater;

    static {
        updater = AtomicIntegerFieldUpdater.newUpdater(SecurityBug.class, "theField");
    }

    private volatile int theField;

    public static void main(String[] args) throws Exception {
        new SecurityBug();
    }
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Use the AtomicInteger class or relax the security policy.

Comments
EVALUATION http://hg.openjdk.java.net/jdk8/tl/jdk/rev/48513d156965
09-05-2012

PUBLIC COMMENTS The access control exception comes from a call to getDeclaredField: java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers") at java.security.AccessControlContext.checkPermission(AccessControlContext.java:366) at java.security.AccessController.checkPermission(AccessController.java:555) at java.lang.SecurityManager.checkPermission(SecurityManager.java:549) at java.lang.SecurityManager.checkMemberAccess(SecurityManager.java:1679) at java.lang.Class.checkMemberAccess(Class.java:2174) at java.lang.Class.getDeclaredField(Class.java:1896) at java.util.concurrent.atomic.AtomicIntegerFieldUpdater$AtomicIntegerFieldUpdaterImpl.<init>(AtomicIntegerFieldUpdater.java:276) when this occurs from the AtomicIntegerFieldUpdater implementation access is denied. But if the application itself calls getDeclaredField directly then it works. According to the docs for getDeclaredField a security exception is thrown when a security manager, s, is present and any of the following conditions is met: invocation of s.checkMemberAccess(this, Member.DECLARED) denies access to the declared field the caller's class loader is not the same as or an ancestor of the class loader for the current class and invocation of s.checkPackageAccess() denies access to the package of this class Looking at SecurityManager we see that checkMemberAccess will call checkPermission if the caller's classloader and the target class's classloader are different - which they are. This explains why a direct call to getDeclaredField works. checkPermission simply delegates to AccessController.checkPermission. That check would pass if we had privileged system code on the stack. But the atomic updater does not use doPrivileged. It should.
22-10-2011

EVALUATION The AtomicFieldUpdater implementation invokes class.getDeclaredField() without using a doPrivileged block. As a result, because the AtomicFieldUpdater class and the application class are in different packages, the SecurityManager will invoke AccessController.checkPermission and that will fail (unless the requisite permission has been set in the current security policy). We need to call getDeclaredField in a doPrivileged block.
22-10-2011