Skip to content
Permalink
Browse files
[lworld] small reflection implementation clean up
  • Loading branch information
Mandy Chung committed Jun 18, 2020
1 parent 45e20dc commit 9cdd26f6c38bbcd4414e0a93b71450ab2a01afde
Showing 7 changed files with 55 additions and 96 deletions.
@@ -55,7 +55,7 @@
* @see LambdaMetafactory
*/
/* package */ final class InnerClassLambdaMetafactory extends AbstractValidatingLambdaMetafactory {
private static final int CLASSFILE_VERSION = 52;
private static final int CLASSFILE_VERSION = V15;
private static final String METHOD_DESCRIPTOR_VOID = Type.getMethodDescriptor(Type.VOID_TYPE);
private static final String JAVA_LANG_OBJECT = "java/lang/Object";
private static final String NAME_CTOR = "<init>";
@@ -177,7 +177,8 @@ public static void setAccessible(AccessibleObject[] array, boolean flag) {
* to the caller's module. </p>
*
* <p> This method cannot be used to enable {@linkplain Field#set <em>write</em>}
* access to a final field declared in a {@linkplain Class#isHidden() hidden class},
* access to a final field declared in a {@linkplain Class#isHidden() hidden class}
* and an {@linkplain Class#isInlineClass() inline class},
* since such fields are not modifiable. The {@code accessible} flag when
* {@code true} suppresses Java language access control checks to only
* enable {@linkplain Field#get <em>read</em>} access to such fields.
@@ -309,19 +310,6 @@ private boolean checkCanSetAccessible(Class<?> caller,
modifiers = ((Field) this).getModifiers();
}

// Do not allow suppression of access check for inline class's field
if (declaringClass.isInlineClass() &&
this instanceof Field
&& Modifier.isFinal(modifiers)) {
if (throwExceptionIfDenied) {
String msg = "Unable to make field accessible of inline class "
+ declaringClass.getName();
throw new InaccessibleObjectException(msg);
} else {
return false;
}
}

Module callerModule = caller.getModule();
Module declaringModule = declaringClass.getModule();

@@ -166,10 +166,6 @@ Field copy() {
public void setAccessible(boolean flag) {
AccessibleObject.checkPermission();

if (clazz.isInlineClass()) {
throw new InaccessibleObjectException("cannot make a field accessible of inline class "
+ clazz.getName());
}
if (flag) {
checkCanSetAccessible(Reflection.getCallerClass());
}
@@ -420,8 +420,7 @@ protected boolean isPrivate() {
return "[" + getClassName(c.getComponentType(), true);
} else {
if (addPrefixAndSuffixForNonPrimitiveTypes) {
final String desc = (c.isInlineClass() ? 'Q' : 'L') + c.getName() + ";";
return internalize(desc);
return c.descriptorString();
} else {
return internalize(c.getName());
}
@@ -81,7 +81,7 @@ public void set(Object obj, Object value)
if (isFlattened()) {
unsafe.putValue(obj, fieldOffset, field.getType(), value);
} else {
unsafe.putReference(obj, fieldOffset, value);
unsafe.putReference(obj, fieldOffset, value);
}
}

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,18 +25,20 @@
/*
* @test
* @summary Test reflection of constructors for inline classes
* @run main/othervm InlineConstructorTest
* @run testng/othervm InlineConstructorTest
*/

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InaccessibleObjectException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;

import org.testng.annotations.Test;
import static org.testng.Assert.*;

public class InlineConstructorTest {

// Target test class
@@ -52,42 +54,32 @@ public SimpleInline(int x) {
}
}

private final Class<?> c;

public static void main(String... args) throws Exception {
testSimpleInlineClass();
}

static void testSimpleInlineClass() throws Exception {
InlineConstructorTest test = new InlineConstructorTest(SimpleInline.class);
test.constructor();
test.constructors("public InlineConstructorTest$SimpleInline(int)",
"InlineConstructorTest$SimpleInline()");
test.setAccessible();
test.trySetAccessible();
test.initFactoryNotMethods();
}
static final Class<?> INLINE_TYPE = SimpleInline.class;

InlineConstructorTest(Class<?> type) throws Exception {
String cn = type.getName();
this.c = Class.forName(cn);
@Test
public static void testInlineClassConstructor() throws Exception {
String cn = INLINE_TYPE.getName();
Class<?> c = Class.forName(cn);

assertTrue(c.isInlineClass());
assertEquals(c, type);
assertEquals(c, INLINE_TYPE);
}

void constructor() throws Exception {
Constructor<?> ctor = c.getDeclaredConstructor();
@Test
public static void constructor() throws Exception {
Constructor<?> ctor = INLINE_TYPE.getDeclaredConstructor();
Object o = ctor.newInstance();
assertEquals(o.getClass(), c);
assertEquals(o.getClass(), INLINE_TYPE);
}

// Check that the class has the expected Constructors
void constructors(String... expected) throws Exception {
Constructor<? extends Object>[] cons = c.getDeclaredConstructors();
Set<String> actualSig =
Arrays.stream(cons).map(Constructor::toString).collect(Collectors.toSet());
Set<String> expectedSig = Set.of(expected);
@Test
public static void constructors() throws Exception {
Set<String> expectedSig = Set.of("public InlineConstructorTest$SimpleInline(int)",
"InlineConstructorTest$SimpleInline()");
Constructor<? extends Object>[] cons = INLINE_TYPE.getDeclaredConstructors();
Set<String> actualSig = Arrays.stream(cons).map(Constructor::toString)
.collect(Collectors.toSet());
boolean ok = expectedSig.equals(actualSig);
if (!ok) {
System.out.printf("expected: %s%n", expectedSig);
@@ -96,53 +88,43 @@ void constructors(String... expected) throws Exception {
}
}

// Check that the constructor can be set accessible and that the field x can not
void setAccessible() throws Exception {
Constructor<?> ctor = c.getDeclaredConstructor();
// Check that the constructor and field can be set accessible
@Test
public static void setAccessible() throws Exception {
Constructor<?> ctor = INLINE_TYPE.getDeclaredConstructor();
ctor.setAccessible(true);
Field field = c.getField("x");
try {
field.setAccessible(true);
throw new RuntimeException("InaccessibleObjectException not thrown");
} catch (InaccessibleObjectException e) {
// IOE is expected
}

Field field = INLINE_TYPE.getField("x");
field.setAccessible(true);
}

// Check that the constructor can be set accessible and that the field x can not
void trySetAccessible() throws Exception {
Constructor<?> ctor = c.getDeclaredConstructor();
// Check that the constructor and field can be set accessible
@Test
public static void trySetAccessible() throws Exception {
Constructor<?> ctor = INLINE_TYPE.getDeclaredConstructor();
assertTrue(ctor.trySetAccessible());
Field field = c.getField("x");
if (field.trySetAccessible()) {
throw new RuntimeException("trySetAccessible should not succeed");
}

Field field = INLINE_TYPE.getField("x");
assertTrue(field.trySetAccessible());
}

// Check that the final field cannot be modified
@Test(expectedExceptions = IllegalAccessException.class)
public static void setFinalField() throws Exception {
Field field = INLINE_TYPE.getField("x");
field.setAccessible(true);
field.setInt(new SimpleInline(100), 200);
}


// Check that the class does not have a static method with the name <init>
void initFactoryNotMethods() {
Method[] methods = c.getDeclaredMethods();
@Test
public static void initFactoryNotMethods() {
Method[] methods = INLINE_TYPE.getDeclaredMethods();
for (Method m : methods) {
if (Modifier.isStatic(m.getModifiers())) {
assertFalse(m.getName().equals("<init>"));
}
}
}

static void assertEquals(Object o1, Object o2) {
if (o1 == o2 || o1.equals(o2))
return;

throw new AssertionError(o1 + " != " + o2);
}

static void assertTrue(boolean value) {
if (!value)
throw new AssertionError("expected true");
}

static void assertFalse(boolean value) {
if (value)
throw new AssertionError("expected false");
}
}
@@ -31,7 +31,6 @@
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InaccessibleObjectException;
import java.lang.reflect.Method;

import org.testng.annotations.Test;
@@ -192,13 +191,8 @@ void constructor() throws Exception {

void staticField() throws Exception {
Field f = c.getDeclaredField("STATIC_FIELD");
if (f.trySetAccessible()) {
throw new RuntimeException("trySetAccessible should not succeed");
}
try {
f.setAccessible(true);
throw new RuntimeException("IllegalAccessException not thrown");
} catch (InaccessibleObjectException e) { }
f.trySetAccessible();
assertTrue(f.isAccessible());
}

void checkField(String source, String name, Class<?> type) throws Exception {

0 comments on commit 9cdd26f

Please sign in to comment.