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 TrySetAccessibleTest
  31  * @summary Test AccessibleObject::trySetAccessible method
  32  */
  33 
  34 import java.lang.reflect.AccessibleObject;
  35 import java.lang.reflect.Constructor;
  36 import java.lang.reflect.Field;
  37 import java.lang.reflect.InvocationTargetException;
  38 import java.lang.reflect.Method;
  39 
  40 import jdk.internal.misc.Unsafe;
  41 import jdk.internal.perf.Perf;
  42 
  43 import org.testng.annotations.Test;
  44 import static org.testng.Assert.*;
  45 
  46 @Test
  47 public 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 }