1 /* 2 * Copyright (c) 2012, 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 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 enum TYPE { INT, LONG, REF } 51 52 static class Config { 53 final Class<?> clazz; 54 final String field; 55 final String access; 56 final boolean reflectOk; 57 final boolean updaterOk; 58 final String desc; 59 final TYPE type; 60 61 Config(Class<?> clazz, String field, String access, 62 boolean reflectOk, boolean updaterOk, String desc, TYPE type) { 63 this.clazz = clazz; 64 this.field = field; 65 this.access = access; 66 this.reflectOk = reflectOk; 67 this.updaterOk = updaterOk; 68 this.desc = desc; 69 this.type =type; 70 } 71 72 public String toString() { 73 return desc + ": " + access + " " + clazz.getName() + "." + field; 74 } 75 } 76 77 static Config[] tests; 78 79 static void initTests(boolean hasSM) { 80 tests = new Config[] { 81 new Config(AtomicUpdaters.class, "pub_int", "public", true, true, "public int field of current class", TYPE.INT), 82 new Config(AtomicUpdaters.class, "priv_int", "private", true, true, "private int field of current class", TYPE.INT), 83 new Config(AtomicUpdaters.class, "pub_long", "public", true, true, "public long field of current class", TYPE.LONG), 84 new Config(AtomicUpdaters.class, "priv_long", "private", true, true, "private long field of current class", TYPE.LONG), 85 new Config(AtomicUpdaters.class, "pub_ref", "public", true, true, "public ref field of current class", TYPE.REF), 86 new Config(AtomicUpdaters.class, "priv_ref", "private", true, true, "private ref field of current class", TYPE.REF), 87 88 // Would like to test a public volatile in a class in another 89 // package - but of course there aren't any 90 new Config(AtomicInteger.class, "value", "private", hasSM ? false : true, false, "private int field of class in different package", TYPE.INT), 91 new Config(AtomicLong.class, "value", "private", hasSM ? false : true, false, "private long field of class in different package", TYPE.LONG), 92 new Config(AtomicReference.class, "value", "private", hasSM ? false : true, false, "private reference field of class in different package", TYPE.REF), 93 }; 94 } 95 96 public volatile int pub_int; 97 private volatile int priv_int; 98 public volatile long pub_long; 99 private volatile long priv_long; 100 public volatile Object pub_ref; 101 private volatile Object priv_ref; 102 103 104 // This should be set dynamically at runtime using a System property, but 105 // ironically we get a SecurityException if we try to do that with a 106 // SecurityManager installed 107 static boolean verbose; 108 109 public static void main(String[] args) throws Throwable { 110 boolean hasSM = false; 111 for (String arg : args) { 112 if ("-v".equals(arg)) { 113 verbose = true; 114 } 115 else if ("UseSM".equals(arg)) { 116 // Ensure that the test is not influenced by the default users policy. 117 Policy.setPolicy(new NoPermissionsPolicy()); 118 SecurityManager m = System.getSecurityManager(); 119 if (m != null) 120 throw new RuntimeException("No security manager should initially be installed"); 121 System.setSecurityManager(new java.lang.SecurityManager()); 122 hasSM = true; 123 } 124 else { 125 throw new IllegalArgumentException("Unexpected option: " + arg); 126 } 127 } 128 initTests(hasSM); 129 130 int failures = 0; 131 132 System.out.printf("Testing with%s a SecurityManager present\n", hasSM ? "" : "out"); 133 for (Config c : tests) { 134 System.out.println("Testing: " + c); 135 Error reflectionFailure = null; 136 Error updaterFailure = null; 137 Class<?> clazz = c.clazz; 138 // See if we can reflectively access the field 139 System.out.println(" - testing getDeclaredField"); 140 try { 141 Field f = clazz.getDeclaredField(c.field); 142 if (!c.reflectOk) 143 reflectionFailure = new Error("Unexpected reflective access: " + c); 144 } 145 catch (AccessControlException e) { 146 if (c.reflectOk) 147 reflectionFailure = new Error("Unexpected reflective access failure: " + c, e); 148 else if (verbose) { 149 System.out.println("Got expected reflection exception: " + e); 150 e.printStackTrace(System.out); 151 } 152 } 153 154 if (reflectionFailure != null) { 155 reflectionFailure.printStackTrace(System.out); 156 } 157 158 // see if we can create an atomic updater for the field 159 Object u = null; 160 try { 161 switch (c.type) { 162 case INT: 163 System.out.println(" - testing AtomicIntegerFieldUpdater"); 164 u = AtomicIntegerFieldUpdater.newUpdater(clazz, c.field); 165 break; 166 case LONG: 167 System.out.println(" - testing AtomicLongFieldUpdater"); 168 u = AtomicLongFieldUpdater.newUpdater(clazz, c.field); 169 break; 170 case REF: 171 System.out.println(" - testing AtomicReferenceFieldUpdater"); 172 u = AtomicReferenceFieldUpdater.newUpdater(clazz, Object.class, c.field); 173 break; 174 } 175 176 if (!c.updaterOk) 177 updaterFailure = new Error("Unexpected updater access: " + c); 178 } 179 catch (Exception e) { 180 if (c.updaterOk) 181 updaterFailure = new Error("Unexpected updater access failure: " + c, e); 182 else if (verbose) { 183 System.out.println("Got expected updater exception: " + e); 184 e.printStackTrace(System.out); 185 } 186 } 187 188 if (updaterFailure != null) { 189 updaterFailure.printStackTrace(System.out); 190 } 191 192 if (updaterFailure != null || reflectionFailure != null) { 193 failures++; 194 195 } 196 } 197 198 if (failures > 0) { 199 throw new Error("Some tests failed - see previous stacktraces"); 200 } 201 } 202 203 /** 204 * Policy with no permissions. 205 */ 206 private static class NoPermissionsPolicy extends Policy { 207 @Override 208 public PermissionCollection getPermissions(CodeSource cs) { 209 return Policy.UNSUPPORTED_EMPTY_COLLECTION; 210 } 211 212 @Override 213 public PermissionCollection getPermissions(ProtectionDomain pd) { 214 return Policy.UNSUPPORTED_EMPTY_COLLECTION; 215 } 216 217 @Override 218 public boolean implies(ProtectionDomain pd, Permission p) { 219 return Policy.UNSUPPORTED_EMPTY_COLLECTION.implies(p); 220 } 221 } 222 }