1 /* 2 * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @bug 7103570 8189291 27 * @author David Holmes 28 * @run main/othervm AtomicUpdaters 29 * @run main/othervm AtomicUpdaters UseSM 30 * @summary Checks the (in)ability to create field updaters for differently 31 * accessible fields in different locations with/without a security 32 * manager 33 */ 34 35 import java.lang.reflect.Field; 36 import java.security.AccessControlException; 37 import java.security.CodeSource; 38 import java.security.Permission; 39 import java.security.PermissionCollection; 40 import java.security.Policy; 41 import java.security.ProtectionDomain; 42 import java.util.concurrent.atomic.AtomicInteger; 43 import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; 44 import java.util.concurrent.atomic.AtomicLong; 45 import java.util.concurrent.atomic.AtomicLongFieldUpdater; 46 import java.util.concurrent.atomic.AtomicReference; 47 import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; 48 49 public class AtomicUpdaters { 50 static final Policy DEFAULT_POLICY = Policy.getPolicy(); 51 52 enum TYPE { INT, LONG, REF } 53 54 static class Config { 55 final Class<?> clazz; 56 final String field; 57 final String access; 58 final boolean reflectOk; 59 final boolean updaterOk; 60 final String desc; 61 final TYPE type; 62 Config(Class<?> clazz, String field, String access, boolean reflectOk, boolean updaterOk, String desc, TYPE type)63 Config(Class<?> clazz, String field, String access, 64 boolean reflectOk, boolean updaterOk, String desc, TYPE type) { 65 this.clazz = clazz; 66 this.field = field; 67 this.access = access; 68 this.reflectOk = reflectOk; 69 this.updaterOk = updaterOk; 70 this.desc = desc; 71 this.type =type; 72 } 73 toString()74 public String toString() { 75 return desc + ": " + access + " " + clazz.getName() + "." + field; 76 } 77 } 78 79 static Config[] tests; 80 initTests(boolean hasSM)81 static void initTests(boolean hasSM) { 82 tests = new Config[] { 83 new Config(AtomicUpdaters.class, "pub_int", "public", true, true, "public int field of current class", TYPE.INT), 84 new Config(AtomicUpdaters.class, "priv_int", "private", true, true, "private int field of current class", TYPE.INT), 85 new Config(AtomicUpdaters.class, "pub_long", "public", true, true, "public long field of current class", TYPE.LONG), 86 new Config(AtomicUpdaters.class, "priv_long", "private", true, true, "private long field of current class", TYPE.LONG), 87 new Config(AtomicUpdaters.class, "pub_ref", "public", true, true, "public ref field of current class", TYPE.REF), 88 new Config(AtomicUpdaters.class, "priv_ref", "private", true, true, "private ref field of current class", TYPE.REF), 89 90 // Would like to test a public volatile in a class in another 91 // package - but of course there aren't any 92 new Config(AtomicInteger.class, "value", "private", !hasSM, false, "private int field of class in different package", TYPE.INT), 93 new Config(AtomicLong.class, "value", "private", !hasSM, false, "private long field of class in different package", TYPE.LONG), 94 new Config(AtomicReference.class, "value", "private", !hasSM, false, "private reference field of class in different package", TYPE.REF), 95 }; 96 } 97 98 public volatile int pub_int; 99 private volatile int priv_int; 100 public volatile long pub_long; 101 private volatile long priv_long; 102 public volatile Object pub_ref; 103 private volatile Object priv_ref; 104 105 106 // This should be set dynamically at runtime using a System property, but 107 // ironically we get a SecurityException if we try to do that with a 108 // SecurityManager installed 109 static boolean verbose; 110 main(String[] args)111 public static void main(String[] args) throws Throwable { 112 boolean hasSM = false; 113 for (String arg : args) { 114 if ("-v".equals(arg)) { 115 verbose = true; 116 } 117 else if ("UseSM".equals(arg)) { 118 // Ensure that the test is not influenced by the default users policy. 119 Policy.setPolicy(new NoPermissionsPolicy()); 120 SecurityManager m = System.getSecurityManager(); 121 if (m != null) 122 throw new RuntimeException("No security manager should initially be installed"); 123 System.setSecurityManager(new java.lang.SecurityManager()); 124 hasSM = true; 125 } 126 else { 127 throw new IllegalArgumentException("Unexpected option: " + arg); 128 } 129 } 130 initTests(hasSM); 131 132 int failures = 0; 133 134 System.out.printf("Testing with%s a SecurityManager present\n", hasSM ? "" : "out"); 135 for (Config c : tests) { 136 System.out.println("Testing: " + c); 137 Error reflectionFailure = null; 138 Error updaterFailure = null; 139 Class<?> clazz = c.clazz; 140 // See if we can reflectively access the field 141 System.out.println(" - testing getDeclaredField"); 142 try { 143 Field f = clazz.getDeclaredField(c.field); 144 if (!c.reflectOk) 145 reflectionFailure = new Error("Unexpected reflective access: " + c); 146 } 147 catch (AccessControlException e) { 148 if (c.reflectOk) 149 reflectionFailure = new Error("Unexpected reflective access failure: " + c, e); 150 else if (verbose) { 151 System.out.println("Got expected reflection exception: " + e); 152 e.printStackTrace(System.out); 153 } 154 } 155 156 if (reflectionFailure != null) { 157 reflectionFailure.printStackTrace(System.out); 158 } 159 160 // see if we can create an atomic updater for the field 161 Object u = null; 162 try { 163 switch (c.type) { 164 case INT: 165 System.out.println(" - testing AtomicIntegerFieldUpdater"); 166 u = AtomicIntegerFieldUpdater.newUpdater(clazz, c.field); 167 break; 168 case LONG: 169 System.out.println(" - testing AtomicLongFieldUpdater"); 170 u = AtomicLongFieldUpdater.newUpdater(clazz, c.field); 171 break; 172 case REF: 173 System.out.println(" - testing AtomicReferenceFieldUpdater"); 174 u = AtomicReferenceFieldUpdater.newUpdater(clazz, Object.class, c.field); 175 break; 176 } 177 178 if (!c.updaterOk) 179 updaterFailure = new Error("Unexpected updater access: " + c); 180 } 181 catch (Exception e) { 182 if (c.updaterOk) 183 updaterFailure = new Error("Unexpected updater access failure: " + c, e); 184 else if (verbose) { 185 System.out.println("Got expected updater exception: " + e); 186 e.printStackTrace(System.out); 187 } 188 } 189 190 if (updaterFailure != null) { 191 updaterFailure.printStackTrace(System.out); 192 } 193 194 if (updaterFailure != null || reflectionFailure != null) { 195 failures++; 196 197 } 198 } 199 200 if (failures > 0) { 201 throw new Error("Some tests failed - see previous stacktraces"); 202 } 203 } 204 205 /** 206 * Policy with no permissions. 207 */ 208 private static class NoPermissionsPolicy extends Policy { 209 @Override getPermissions(CodeSource cs)210 public PermissionCollection getPermissions(CodeSource cs) { 211 return Policy.UNSUPPORTED_EMPTY_COLLECTION; 212 } 213 214 @Override getPermissions(ProtectionDomain pd)215 public PermissionCollection getPermissions(ProtectionDomain pd) { 216 return Policy.UNSUPPORTED_EMPTY_COLLECTION; 217 } 218 219 @Override implies(ProtectionDomain pd, Permission p)220 public boolean implies(ProtectionDomain pd, Permission p) { 221 return Policy.UNSUPPORTED_EMPTY_COLLECTION.implies(p) || 222 DEFAULT_POLICY.implies(pd, p); 223 } 224 } 225 } 226