File: AtomicUpdaters.java

package info (click to toggle)
openjdk-11 11.0.4%2B11-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 757,028 kB
  • sloc: java: 5,016,041; xml: 1,191,974; cpp: 934,731; ansic: 555,697; sh: 24,299; objc: 12,703; python: 3,602; asm: 3,415; makefile: 2,772; awk: 351; sed: 172; perl: 114; jsp: 24; csh: 3
file content (225 lines) | stat: -rw-r--r-- 9,077 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
/*
 * Copyright (c) 2012, 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.
 */

/*
 * @test
 * @bug 7103570 8189291
 * @author David Holmes
 * @run main/othervm AtomicUpdaters
 * @run main/othervm AtomicUpdaters UseSM
 * @summary Checks the (in)ability to create field updaters for differently
 *          accessible fields in different locations with/without a security
 *          manager
 */

import java.lang.reflect.Field;
import java.security.AccessControlException;
import java.security.CodeSource;
import java.security.Permission;
import java.security.PermissionCollection;
import java.security.Policy;
import java.security.ProtectionDomain;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicLongFieldUpdater;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;

public class  AtomicUpdaters {
    static final Policy DEFAULT_POLICY = Policy.getPolicy();

    enum TYPE { INT, LONG, REF }

    static class Config {
        final Class<?> clazz;
        final String field;
        final String access;
        final boolean reflectOk;
        final boolean updaterOk;
        final String desc;
        final TYPE type;

        Config(Class<?> clazz, String field, String access,
               boolean reflectOk, boolean updaterOk, String desc, TYPE type) {
            this.clazz = clazz;
            this.field = field;
            this.access = access;
            this.reflectOk = reflectOk;
            this.updaterOk = updaterOk;
            this.desc = desc;
            this.type =type;
        }

        public String toString() {
            return desc + ": " + access + " " + clazz.getName() + "." + field;
        }
    }

    static Config[] tests;

    static void initTests(boolean hasSM) {
        tests = new Config[] {
            new Config(AtomicUpdaters.class, "pub_int", "public", true, true, "public int field of current class", TYPE.INT),
            new Config(AtomicUpdaters.class, "priv_int", "private", true, true, "private int field of current class", TYPE.INT),
            new Config(AtomicUpdaters.class, "pub_long", "public", true, true, "public long field of current class", TYPE.LONG),
            new Config(AtomicUpdaters.class, "priv_long", "private", true, true, "private long field of current class", TYPE.LONG),
            new Config(AtomicUpdaters.class, "pub_ref", "public", true, true, "public ref field of current class", TYPE.REF),
            new Config(AtomicUpdaters.class, "priv_ref", "private", true, true, "private ref field of current class", TYPE.REF),

            // Would like to test a public volatile in a class in another
            // package - but of course there aren't any
            new Config(AtomicInteger.class, "value", "private", !hasSM, false, "private int field of class in different package", TYPE.INT),
            new Config(AtomicLong.class, "value", "private", !hasSM, false, "private long field of class in different package", TYPE.LONG),
            new Config(AtomicReference.class, "value", "private", !hasSM, false, "private reference field of class in different package", TYPE.REF),
        };
    }

    public volatile int pub_int;
    private volatile int priv_int;
    public volatile long pub_long;
    private volatile long priv_long;
    public volatile Object pub_ref;
    private volatile Object priv_ref;


    // This should be set dynamically at runtime using a System property, but
    // ironically we get a SecurityException if we try to do that with a
    // SecurityManager installed
    static boolean verbose;

    public static void main(String[] args) throws Throwable {
        boolean hasSM = false;
        for (String arg : args) {
            if ("-v".equals(arg)) {
                verbose = true;
            }
            else if ("UseSM".equals(arg)) {
                // Ensure that the test is not influenced by the default users policy.
                Policy.setPolicy(new NoPermissionsPolicy());
                SecurityManager m = System.getSecurityManager();
                if (m != null)
                    throw new RuntimeException("No security manager should initially be installed");
                System.setSecurityManager(new java.lang.SecurityManager());
                hasSM = true;
            }
            else {
                throw new IllegalArgumentException("Unexpected option: " + arg);
            }
        }
        initTests(hasSM);

        int failures = 0;

        System.out.printf("Testing with%s a SecurityManager present\n", hasSM ? "" : "out");
        for (Config c : tests) {
            System.out.println("Testing: " + c);
            Error reflectionFailure = null;
            Error updaterFailure = null;
            Class<?> clazz = c.clazz;
            // See if we can reflectively access the field
            System.out.println(" - testing getDeclaredField");
            try {
                Field f = clazz.getDeclaredField(c.field);
                if (!c.reflectOk)
                    reflectionFailure = new Error("Unexpected reflective access: " + c);
            }
            catch (AccessControlException e) {
                if (c.reflectOk)
                    reflectionFailure = new Error("Unexpected reflective access failure: " + c, e);
                else if (verbose) {
                    System.out.println("Got expected reflection exception: " + e);
                    e.printStackTrace(System.out);
                }
            }

            if (reflectionFailure != null) {
                reflectionFailure.printStackTrace(System.out);
            }

            // see if we can create an atomic updater for the field
            Object u = null;
            try {
                switch (c.type) {
                case INT:
                    System.out.println(" - testing AtomicIntegerFieldUpdater");
                    u = AtomicIntegerFieldUpdater.newUpdater(clazz, c.field);
                    break;
                case LONG:
                    System.out.println(" - testing AtomicLongFieldUpdater");
                    u = AtomicLongFieldUpdater.newUpdater(clazz, c.field);
                    break;
                case REF:
                    System.out.println(" - testing AtomicReferenceFieldUpdater");
                    u = AtomicReferenceFieldUpdater.newUpdater(clazz, Object.class, c.field);
                    break;
                }

                if (!c.updaterOk)
                    updaterFailure =  new Error("Unexpected updater access: " + c);
            }
            catch (Exception e) {
                if (c.updaterOk)
                    updaterFailure = new Error("Unexpected updater access failure: " + c, e);
                else if (verbose) {
                    System.out.println("Got expected updater exception: " + e);
                    e.printStackTrace(System.out);
                }
            }

            if (updaterFailure != null) {
                updaterFailure.printStackTrace(System.out);
            }

            if (updaterFailure != null || reflectionFailure != null) {
                failures++;

            }
        }

        if (failures > 0) {
            throw new Error("Some tests failed - see previous stacktraces");
        }
    }

    /**
     * Policy with no permissions.
     */
    private static class NoPermissionsPolicy extends Policy {
        @Override
        public PermissionCollection getPermissions(CodeSource cs) {
            return Policy.UNSUPPORTED_EMPTY_COLLECTION;
        }

        @Override
        public PermissionCollection getPermissions(ProtectionDomain pd) {
            return Policy.UNSUPPORTED_EMPTY_COLLECTION;
        }

        @Override
        public boolean implies(ProtectionDomain pd, Permission p) {
            return Policy.UNSUPPORTED_EMPTY_COLLECTION.implies(p) ||
                    DEFAULT_POLICY.implies(pd, p);
        }
    }
}