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