1 /*
  2  * Copyright (c) 2017, 2025, 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  * @build TrySetAccessibleTest
 27  * @modules java.base/java.lang:open
 28  *          java.base/jdk.internal.module
 29  *          java.base/jdk.internal.perf
 30  *          java.base/jdk.internal.misc:+open
 31  * @run testng/othervm TrySetAccessibleTest
 32  * @summary Test AccessibleObject::trySetAccessible method
 33  */
 34 
 35 import java.lang.reflect.AccessibleObject;
 36 import java.lang.reflect.Constructor;
 37 import java.lang.reflect.Field;
 38 import java.lang.reflect.InvocationTargetException;
 39 import java.lang.reflect.Method;
 40 
 41 import jdk.internal.misc.Unsafe;
 42 import jdk.internal.module.ModulePath;
 43 import jdk.internal.perf.Perf;
 44 import java.security.ProtectionDomain;
 45 
 46 import org.testng.annotations.Test;
 47 import static org.testng.Assert.*;
 48 
 49 @Test
 50 public class TrySetAccessibleTest {
 51     /**
 52      * Invoke a private constructor on a public class in an exported package
 53      */
 54     public void testPrivateConstructorInExportedPackage() throws Exception {
 55         Constructor<?> ctor = Perf.class.getDeclaredConstructor();
 56 
 57         try {
 58             ctor.newInstance();
 59             assertTrue(false);
 60         } catch (IllegalAccessException expected) { }
 61 
 62         assertFalse(ctor.trySetAccessible());
 63         assertFalse(ctor.canAccess(null));
 64     }
 65 
 66     /**
 67      * Invoke a private constructor on a public class in an open package
 68      */
 69     public void testPrivateConstructorInOpenedPackage() throws Exception {
 70         Constructor<?> ctor = Unsafe.class.getDeclaredConstructor();
 71 
 72         try {
 73             ctor.newInstance();
 74             assertTrue(false);
 75         } catch (IllegalAccessException expected) { }
 76 
 77         assertTrue(ctor.trySetAccessible());
 78         assertTrue(ctor.canAccess(null));
 79         Unsafe unsafe = (Unsafe) ctor.newInstance();
 80     }
 81 
 82     /**
 83      * Invoke a private method on a public class in an exported package
 84      */
 85     public void testPrivateMethodInExportedPackage() throws Exception {
 86         Method m = ModulePath.class.getDeclaredMethod("packageName", String.class);
 87         try {
 88             m.invoke(null);
 89             assertTrue(false);
 90         } catch (IllegalAccessException expected) { }
 91 
 92         assertFalse(m.trySetAccessible());
 93         assertFalse(m.canAccess(null));
 94     }
 95 
 96 
 97     /**
 98      * Invoke a private method on a public class in an open package
 99      */
100     public void testPrivateMethodInOpenedPackage() throws Exception {
101         Method m = Unsafe.class.getDeclaredMethod("throwIllegalAccessError");
102         assertFalse(m.canAccess(null));
103 
104         try {
105             m.invoke(null);
106             assertTrue(false);
107         } catch (IllegalAccessException expected) { }
108 
109         assertTrue(m.trySetAccessible());
110         assertTrue(m.canAccess(null));
111         try {
112             m.invoke(null);
113             assertTrue(false);
114         } catch (InvocationTargetException e) {
115             // thrown by throwIllegalAccessError
116             assertTrue(e.getCause() instanceof IllegalAccessError);
117         }
118     }
119 
120     /**
121      * Invoke a private method on a public class in an exported package
122      */
123     public void testPrivateFieldInExportedPackage() throws Exception {
124         Field f = Perf.class.getDeclaredField("instance");
125         try {
126             f.get(null);
127             assertTrue(false);
128         } catch (IllegalAccessException expected) { }
129 
130         assertFalse(f.trySetAccessible());
131         assertFalse(f.canAccess(null));
132         try {
133             f.get(null);
134             assertTrue(false);
135         } catch (IllegalAccessException expected) {}
136     }
137 
138     /**
139      * Access a private field in a public class that is an exported package
140      */
141     public void testPrivateFieldInOpenedPackage() throws Exception {
142         Field f = Unsafe.class.getDeclaredField("theUnsafe");
143 
144         try {
145             f.get(null);
146             assertTrue(false);
147         } catch (IllegalAccessException expected) { }
148 
149         assertTrue(f.trySetAccessible());
150         assertTrue(f.canAccess(null));
151         Unsafe unsafe = (Unsafe) f.get(null);
152     }
153 
154 
155     /**
156      * Invoke a public constructor on a public class in a non-exported package
157      */
158     public void testPublicConstructorInNonExportedPackage() throws Exception {
159         Class<?> clazz = Class.forName("sun.security.x509.X500Name");
160         Constructor<?> ctor = clazz.getConstructor(String.class);
161 
162         try {
163             ctor.newInstance("cn=duke");
164             assertTrue(false);
165         } catch (IllegalAccessException expected) { }
166 
167         assertFalse(ctor.trySetAccessible());
168         assertFalse(ctor.canAccess(null));
169         assertTrue(ctor.trySetAccessible() == ctor.isAccessible());
170     }
171 
172 
173     /**
174      * Access a public field in a public class that in a non-exported package
175      */
176     public void testPublicFieldInNonExportedPackage() throws Exception {
177         Class<?> clazz = Class.forName("sun.security.x509.X500Name");
178         Field f = clazz.getField("SERIALNUMBER_OID");
179 
180         try {
181             f.get(null);
182             assertTrue(false);
183         } catch (IllegalAccessException expected) { }
184 
185         assertFalse(f.trySetAccessible());
186         assertFalse(f.canAccess(null));
187     }
188 
189 
190     /**
191      * Test that the Class constructor cannot be make accessible.
192      */
193     public void testJavaLangClass() throws Exception {
194 
195         // non-public constructor
196         Constructor<?> ctor
197             = Class.class.getDeclaredConstructor(ClassLoader.class, Class.class, char.class,
198                                                  ProtectionDomain.class, boolean.class, char.class);
199         AccessibleObject[] ctors = { ctor };
200 
201         assertFalse(ctor.trySetAccessible());
202         assertFalse(ctor.canAccess(null));
203     }
204 
205 }