Fix Class.getModifiers for array classes.
A separate libcore change is needed to fix Class.getModifiers for
arrays of inner classes.
Bug: https://code.google.com/p/android/issues/detail?id=56267
Change-Id: I3d95b266bb14a72b766921fe09e53fdef2f6d01b
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 6e32065..93de3f5 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -2021,15 +2021,16 @@
CHECK(array_iftable_ != NULL);
new_class->SetIfTable(array_iftable_);
- // Inherit access flags from the component type. Arrays can't be
- // used as a superclass or interface, so we want to add "final"
+ // Inherit access flags from the component type.
+ int access_flags = new_class->GetComponentType()->GetAccessFlags();
+ // Lose any implementation detail flags; in particular, arrays aren't finalizable.
+ access_flags &= kAccJavaFlagsMask;
+ // Arrays can't be used as a superclass or interface, so we want to add "abstract final"
// and remove "interface".
- //
- // Don't inherit any non-standard flags (e.g., kAccFinal)
- // from component_type. We assume that the array class does not
- // override finalize().
- new_class->SetAccessFlags(((new_class->GetComponentType()->GetAccessFlags() &
- ~kAccInterface) | kAccFinal) & kAccJavaFlagsMask);
+ access_flags |= kAccAbstract | kAccFinal;
+ access_flags &= ~kAccInterface;
+
+ new_class->SetAccessFlags(access_flags);
mirror::Class* existing = InsertClass(descriptor, new_class.get(), false);
if (existing == NULL) {
diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc
index 73bdc61..4540c01 100644
--- a/src/class_linker_test.cc
+++ b/src/class_linker_test.cc
@@ -90,6 +90,7 @@
EXPECT_TRUE(primitive->GetVTable() == NULL);
EXPECT_EQ(0, primitive->GetIfTableCount());
EXPECT_TRUE(primitive->GetIfTable() == NULL);
+ EXPECT_EQ(kAccPublic | kAccFinal | kAccAbstract, primitive->GetAccessFlags());
}
void AssertArrayClass(const std::string& array_descriptor,
@@ -100,6 +101,7 @@
ClassHelper array_component_ch(array->GetComponentType());
EXPECT_STREQ(component_type.c_str(), array_component_ch.GetDescriptor());
EXPECT_EQ(class_loader, array->GetClassLoader());
+ EXPECT_EQ(kAccFinal | kAccAbstract, (array->GetAccessFlags() & (kAccFinal | kAccAbstract)));
AssertArrayClass(array_descriptor, array);
}
diff --git a/test/031-class-attributes/expected.txt b/test/031-class-attributes/expected.txt
index afa3416..4ae1eed 100644
--- a/test/031-class-attributes/expected.txt
+++ b/test/031-class-attributes/expected.txt
@@ -1,3 +1,25 @@
+public abstract final int
+public abstract final [I
+public java.lang.Object
+public abstract final [Ljava.lang.Object;
+public ClassAttrs$PublicInnerClass
+public abstract final [LClassAttrs$PublicInnerClass;
+protected ClassAttrs$ProtectedInnerClass
+protected abstract final [LClassAttrs$ProtectedInnerClass;
+private ClassAttrs$PrivateInnerClass
+private abstract final [LClassAttrs$PrivateInnerClass;
+ ClassAttrs$PackagePrivateInnerClass
+abstract final [LClassAttrs$PackagePrivateInnerClass;
+public abstract interface java.io.Serializable
+public abstract final [Ljava.io.Serializable;
+public abstract static interface ClassAttrs$PublicInnerInterface
+public abstract final [LClassAttrs$PublicInnerInterface;
+protected abstract static interface ClassAttrs$ProtectedInnerInterface
+protected abstract final [LClassAttrs$ProtectedInnerInterface;
+private abstract static interface ClassAttrs$PrivateInnerInterface
+private abstract final [LClassAttrs$PrivateInnerInterface;
+abstract static interface ClassAttrs$PackagePrivateInnerInterface
+abstract final [LClassAttrs$PackagePrivateInnerInterface;
***** class ClassAttrs:
name: ClassAttrs
canonical: ClassAttrs
@@ -11,8 +33,8 @@
enclosingMeth: null
modifiers: 1
package: null
- declaredClasses: [2] class ClassAttrs$PublicMemberClass, class ClassAttrs$MemberClass
- member classes: [1] class ClassAttrs$PublicMemberClass
+ declaredClasses: [10] class ClassAttrs$PublicMemberClass, class ClassAttrs$MemberClass, interface ClassAttrs$PackagePrivateInnerInterface, interface ClassAttrs$PrivateInnerInterface, interface ClassAttrs$ProtectedInnerInterface, interface ClassAttrs$PublicInnerInterface, class ClassAttrs$PackagePrivateInnerClass, class ClassAttrs$PrivateInnerClass, class ClassAttrs$ProtectedInnerClass, class ClassAttrs$PublicInnerClass
+ member classes: [3] class ClassAttrs$PublicMemberClass, interface ClassAttrs$PublicInnerInterface, class ClassAttrs$PublicInnerClass
isAnnotation: false
isAnonymous: false
isArray: false
diff --git a/test/031-class-attributes/src/ClassAttrs.java b/test/031-class-attributes/src/ClassAttrs.java
index 8719e3b..ae8b2f5 100644
--- a/test/031-class-attributes/src/ClassAttrs.java
+++ b/test/031-class-attributes/src/ClassAttrs.java
@@ -1,10 +1,12 @@
import otherpackage.OtherPackageClass;
+import java.io.Serializable;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
@@ -21,7 +23,72 @@
cinner.showMe();
}
+ public class PublicInnerClass {
+ }
+
+ protected class ProtectedInnerClass {
+ }
+
+ private class PrivateInnerClass {
+ }
+
+ class PackagePrivateInnerClass {
+ }
+
+ public interface PublicInnerInterface {
+ }
+
+ protected interface ProtectedInnerInterface {
+ }
+
+ private interface PrivateInnerInterface {
+ }
+
+ interface PackagePrivateInnerInterface {
+ }
+
+ private static void showModifiers(Class<?> c) {
+ System.out.println(Modifier.toString(c.getModifiers()) + " " + c.getName());
+ }
+
+ // https://code.google.com/p/android/issues/detail?id=56267
+ private static void test56267() {
+ // Primitive classes.
+ showModifiers(int.class);
+ showModifiers(int[].class);
+
+ // Regular classes.
+ showModifiers(Object.class);
+ showModifiers(Object[].class);
+
+ // Inner classes.
+ showModifiers(PublicInnerClass.class);
+ showModifiers(PublicInnerClass[].class);
+ showModifiers(ProtectedInnerClass.class);
+ showModifiers(ProtectedInnerClass[].class);
+ showModifiers(PrivateInnerClass.class);
+ showModifiers(PrivateInnerClass[].class);
+ showModifiers(PackagePrivateInnerClass.class);
+ showModifiers(PackagePrivateInnerClass[].class);
+
+ // Regular interfaces.
+ showModifiers(Serializable.class);
+ showModifiers(Serializable[].class);
+
+ // Inner interfaces.
+ showModifiers(PublicInnerInterface.class);
+ showModifiers(PublicInnerInterface[].class);
+ showModifiers(ProtectedInnerInterface.class);
+ showModifiers(ProtectedInnerInterface[].class);
+ showModifiers(PrivateInnerInterface.class);
+ showModifiers(PrivateInnerInterface[].class);
+ showModifiers(PackagePrivateInnerInterface.class);
+ showModifiers(PackagePrivateInnerInterface[].class);
+ }
+
public static void main() {
+ test56267();
+
printClassAttrs(ClassAttrs.class);
printClassAttrs(OtherClass.class);
printClassAttrs(OtherPackageClass.class);