Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/java/lang/Class/getDeclaredField/FieldSetAccessibleTest.java
38828 views
/*1* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223import java.io.File;24import java.io.FilePermission;25import java.io.IOException;26import java.lang.reflect.Field;27import java.lang.reflect.ReflectPermission;28import java.nio.file.Files;29import java.nio.file.Path;30import java.security.CodeSource;31import java.security.Permission;32import java.security.PermissionCollection;33import java.security.Permissions;34import java.security.Policy;35import java.security.ProtectionDomain;36import java.util.ArrayList;37import java.util.Arrays;38import java.util.Collections;39import java.util.Enumeration;40import java.util.Iterator;41import java.util.List;42import java.util.PropertyPermission;43import java.util.concurrent.atomic.AtomicBoolean;44import java.util.concurrent.atomic.AtomicLong;45import java.util.jar.JarEntry;46import java.util.jar.JarFile;47import java.util.stream.Stream;4849/**50* @test51* @bug 806555252* @summary test that all fields returned by getDeclaredFields() can be53* set accessible if the right permission is granted; this test54* loads all the classes in the BCL, get their declared fields,55* and call setAccessible(false) followed by setAccessible(true);56* @run main/othervm FieldSetAccessibleTest UNSECURE57* @run main/othervm FieldSetAccessibleTest SECURE58*59* @author danielfuchs60*/61public class FieldSetAccessibleTest {6263static final List<String> skipped = new ArrayList<>();64static final List<String> cantread = new ArrayList<>();65static final List<String> failed = new ArrayList<>();66static final AtomicLong classCount = new AtomicLong();67static final AtomicLong fieldCount = new AtomicLong();68static long startIndex = 0;69static long maxSize = Long.MAX_VALUE;70static long maxIndex = Long.MAX_VALUE;717273// Test that all fields for any given class can be made accessibles74static void testSetFieldsAccessible(Class<?> c) {75for (Field f : c.getDeclaredFields()) {76fieldCount.incrementAndGet();77f.setAccessible(false);78f.setAccessible(true);79}80}8182// Performs a series of test on the given class.83// At this time, we only call testSetFieldsAccessible(c)84public static boolean test(Class<?> c) {85//System.out.println(c.getName());86classCount.incrementAndGet();8788// Call getDeclaredFields() and try to set their accessible flag.89testSetFieldsAccessible(c);9091// add more tests here...9293return c == Class.class;94}9596// Prints a summary at the end of the test.97static void printSummary(long secs, long millis, long nanos) {98System.out.println("Tested " + fieldCount.get() + " fields of "99+ classCount.get() + " classes in "100+ secs + "s " + millis + "ms " + nanos + "ns");101}102103104/**105* @param args the command line arguments:106*107* SECURE|UNSECURE [startIndex (default=0)] [maxSize (default=Long.MAX_VALUE)]108*109* @throws java.lang.Exception if the test fails110*/111public static void main(String[] args) throws Exception {112if (args == null || args.length == 0) {113args = new String[] {"SECURE", "0"};114} else if (args.length > 3) {115throw new RuntimeException("Expected at most one argument. Found "116+ Arrays.asList(args));117}118try {119if (args.length > 1) {120startIndex = Long.parseLong(args[1]);121if (startIndex < 0) {122throw new IllegalArgumentException("startIndex args[1]: "123+ startIndex);124}125}126if (args.length > 2) {127maxSize = Long.parseLong(args[2]);128if (maxSize <= 0) {129maxSize = Long.MAX_VALUE;130}131maxIndex = (Long.MAX_VALUE - startIndex) < maxSize132? Long.MAX_VALUE : startIndex + maxSize;133}134TestCase.valueOf(args[0]).run();135} catch (OutOfMemoryError oome) {136System.err.println(classCount.get());137throw oome;138}139}140141public static void run(TestCase test) {142System.out.println("Testing " + test);143test(listAllClassNames());144System.out.println("Passed " + test);145}146147static Iterable<String> listAllClassNames() {148return new ClassNameStreamBuilder();149}150151static void test(Iterable<String> iterable) {152final long start = System.nanoTime();153boolean classFound = false;154int index = 0;155for (String s: iterable) {156if (index == maxIndex) break;157try {158if (index < startIndex) continue;159if (test(s)) {160classFound = true;161}162} finally {163index++;164}165}166long elapsed = System.nanoTime() - start;167long secs = elapsed / 1000_000_000;168long millis = (elapsed % 1000_000_000) / 1000_000;169long nanos = elapsed % 1000_000;170System.out.println("Unreadable path elements: " + cantread);171System.out.println("Skipped path elements: " + skipped);172System.out.println("Failed path elements: " + failed);173printSummary(secs, millis, nanos);174175if (!failed.isEmpty()) {176throw new RuntimeException("Test failed for the following classes: " + failed);177}178if (!classFound && startIndex == 0 && index < maxIndex) {179// this is just to verify that we have indeed parsed rt.jar180// (or the java.base module)181throw new RuntimeException("Test failed: Class.class not found...");182}183if (classCount.get() == 0 && startIndex == 0) {184throw new RuntimeException("Test failed: no class found?");185}186}187188static boolean test(String s) {189try {190if (s.startsWith("WrapperGenerator")) {191System.out.println("Skipping "+ s);192return false;193}194final Class<?> c = Class.forName(195s.replace('/', '.').substring(0, s.length() - 6),196false,197null);198return test(c);199} catch (Exception t) {200t.printStackTrace(System.err);201failed.add(s);202} catch (NoClassDefFoundError e) {203e.printStackTrace(System.err);204failed.add(s);205}206return false;207}208209static class ClassNameStreamBuilder implements Iterable<String>{210String[] bcp;211ClassNameStreamBuilder() {212bcp = System.getProperty("sun.boot.class.path").split(File.pathSeparator);213}214215Stream<String> bcpElementToStream(String s) {216return s.endsWith(".jar") ? jarToStream(s) : folderToStream(s);217}218219Stream<String> jarToStream(String jarName) {220File f = new File(jarName);221if (f.canRead() && f.isFile()) {222try {223JarFile jarFile = new JarFile(f);224return jarFile.stream()225.filter(e -> !e.isDirectory())226.map(JarEntry::getName)227.filter(s -> s.endsWith(".class"));228} catch(IOException x) {229x.printStackTrace(System.err);230skipped.add(jarName);231}232} else {233cantread.add(jarName);234}235return Collections.<String>emptyList().stream();236}237238Stream<String> folderToStream(String folderName) {239final File root = new File(folderName);240if (root.canRead() && root.isDirectory()) {241final Path rootPath = root.toPath();242try {243return Files.walk(rootPath)244.filter(p -> p.getFileName().toString().endsWith(".class"))245.map(rootPath::relativize)246.map(p -> p.toString().replace(File.separatorChar, '/'));247} catch (IOException x) {248x.printStackTrace(System.err);249skipped.add(folderName);250}251} else {252cantread.add(folderName);253}254return Collections.<String>emptyList().stream();255}256257public Stream<String> build() {258return Stream.of(bcp).flatMap(this::bcpElementToStream);259}260261@Override262public Iterator<String> iterator() {263return build().iterator();264}265}266267// Test with or without a security manager268public static enum TestCase {269UNSECURE, SECURE;270public void run() throws Exception {271System.out.println("Running test case: " + name());272Configure.setUp(this);273FieldSetAccessibleTest.run(this);274}275}276277// A helper class to configure the security manager for the test,278// and bypass it when needed.279static class Configure {280static Policy policy = null;281static final ThreadLocal<AtomicBoolean> allowAll = new ThreadLocal<AtomicBoolean>() {282@Override283protected AtomicBoolean initialValue() {284return new AtomicBoolean(false);285}286};287static void setUp(TestCase test) {288switch (test) {289case SECURE:290if (policy == null && System.getSecurityManager() != null) {291throw new IllegalStateException("SecurityManager already set");292} else if (policy == null) {293policy = new SimplePolicy(TestCase.SECURE, allowAll);294Policy.setPolicy(policy);295System.setSecurityManager(new SecurityManager());296}297if (System.getSecurityManager() == null) {298throw new IllegalStateException("No SecurityManager.");299}300if (policy == null) {301throw new IllegalStateException("policy not configured");302}303break;304case UNSECURE:305if (System.getSecurityManager() != null) {306throw new IllegalStateException("SecurityManager already set");307}308break;309default:310throw new InternalError("No such testcase: " + test);311}312}313static void doPrivileged(Runnable run) {314allowAll.get().set(true);315try {316run.run();317} finally {318allowAll.get().set(false);319}320}321}322323// A Helper class to build a set of permissions.324final static class PermissionsBuilder {325final Permissions perms;326public PermissionsBuilder() {327this(new Permissions());328}329public PermissionsBuilder(Permissions perms) {330this.perms = perms;331}332public PermissionsBuilder add(Permission p) {333perms.add(p);334return this;335}336public PermissionsBuilder addAll(PermissionCollection col) {337if (col != null) {338for (Enumeration<Permission> e = col.elements(); e.hasMoreElements(); ) {339perms.add(e.nextElement());340}341}342return this;343}344public Permissions toPermissions() {345final PermissionsBuilder builder = new PermissionsBuilder();346builder.addAll(perms);347return builder.perms;348}349}350351// Policy for the test...352public static class SimplePolicy extends Policy {353354final Permissions permissions;355final Permissions allPermissions;356final ThreadLocal<AtomicBoolean> allowAll;357public SimplePolicy(TestCase test, ThreadLocal<AtomicBoolean> allowAll) {358this.allowAll = allowAll;359360// Permission needed by the tested code exercised in the test361permissions = new Permissions();362permissions.add(new RuntimePermission("fileSystemProvider"));363permissions.add(new RuntimePermission("createClassLoader"));364permissions.add(new RuntimePermission("closeClassLoader"));365permissions.add(new RuntimePermission("getClassLoader"));366permissions.add(new RuntimePermission("accessDeclaredMembers"));367permissions.add(new ReflectPermission("suppressAccessChecks"));368permissions.add(new PropertyPermission("*", "read"));369permissions.add(new FilePermission("<<ALL FILES>>", "read"));370371// these are used for configuring the test itself...372allPermissions = new Permissions();373allPermissions.add(new java.security.AllPermission());374}375376@Override377public boolean implies(ProtectionDomain domain, Permission permission) {378if (allowAll.get().get()) return allPermissions.implies(permission);379if (permissions.implies(permission)) return true;380if (permission instanceof java.lang.RuntimePermission) {381if (permission.getName().startsWith("accessClassInPackage.")) {382// add these along to the set of permission we have, when we383// discover that we need them.384permissions.add(permission);385return true;386}387}388return false;389}390391@Override392public PermissionCollection getPermissions(CodeSource codesource) {393return new PermissionsBuilder().addAll(allowAll.get().get()394? allPermissions : permissions).toPermissions();395}396397@Override398public PermissionCollection getPermissions(ProtectionDomain domain) {399return new PermissionsBuilder().addAll(allowAll.get().get()400? allPermissions : permissions).toPermissions();401}402}403404}405406407