summaryrefslogtreecommitdiffstats
path: root/test/068-classloader
diff options
context:
space:
mode:
authorjeffhao <jeffhao@google.com>2011-09-29 17:41:15 -0700
committerjeffhao <jeffhao@google.com>2011-09-29 17:41:15 -0700
commit5d1ac920fdaef5d4ec8f66bb734488cd9660b024 (patch)
treedd372f306ab70f4c86759869b1f74eca62ff6f2b /test/068-classloader
parentc31664f3d82e6cd68275a529a8a73f067a52e8be (diff)
downloadart-5d1ac920fdaef5d4ec8f66bb734488cd9660b024.zip
art-5d1ac920fdaef5d4ec8f66bb734488cd9660b024.tar.gz
art-5d1ac920fdaef5d4ec8f66bb734488cd9660b024.tar.bz2
Adding old unit tests to test suite.
These tests are copied straight over. They'll still run, but they're using the old system. Change-Id: If494519e52ddf858a9febfc55bdae830468cb3c8
Diffstat (limited to 'test/068-classloader')
-rw-r--r--test/068-classloader/expected.txt13
-rw-r--r--test/068-classloader/info.txt8
-rw-r--r--test/068-classloader/src-ex/AbstractGet.java32
-rw-r--r--test/068-classloader/src-ex/DoubledExtend.java20
-rw-r--r--test/068-classloader/src-ex/DoubledExtendOkay.java36
-rw-r--r--test/068-classloader/src-ex/DoubledImplement.java18
-rw-r--r--test/068-classloader/src-ex/DoubledImplement2.java32
-rw-r--r--test/068-classloader/src-ex/GetDoubled.java26
-rw-r--r--test/068-classloader/src-ex/IfaceImpl.java21
-rw-r--r--test/068-classloader/src-ex/IfaceSub.java19
-rw-r--r--test/068-classloader/src-ex/Inaccessible1.java11
-rw-r--r--test/068-classloader/src-ex/Inaccessible2.java10
-rw-r--r--test/068-classloader/src-ex/Inaccessible3.java10
-rw-r--r--test/068-classloader/src/Base.java16
-rw-r--r--test/068-classloader/src/BaseOkay.java38
-rw-r--r--test/068-classloader/src/DoubledExtend.java20
-rw-r--r--test/068-classloader/src/DoubledExtendOkay.java36
-rw-r--r--test/068-classloader/src/DoubledImplement.java18
-rw-r--r--test/068-classloader/src/DoubledImplement2.java32
-rw-r--r--test/068-classloader/src/FancyLoader.java228
-rw-r--r--test/068-classloader/src/ICommon.java8
-rw-r--r--test/068-classloader/src/ICommon2.java22
-rw-r--r--test/068-classloader/src/IGetDoubled.java22
-rw-r--r--test/068-classloader/src/IfaceSuper.java19
-rw-r--r--test/068-classloader/src/InaccessibleBase.java7
-rw-r--r--test/068-classloader/src/InaccessibleInterface.java7
-rw-r--r--test/068-classloader/src/Main.java425
-rw-r--r--test/068-classloader/src/SimpleBase.java8
-rw-r--r--test/068-classloader/src/Useless.java4
29 files changed, 1166 insertions, 0 deletions
diff --git a/test/068-classloader/expected.txt b/test/068-classloader/expected.txt
new file mode 100644
index 0000000..bf131ee
--- /dev/null
+++ b/test/068-classloader/expected.txt
@@ -0,0 +1,13 @@
+base: class DoubledImplement
+base2: class DoubledImplement2
+Got expected access exception #1
+Got expected CNFE/IAE #2
+Got expected CNFE/IAE #3
+Got expected LinkageError on DE
+Got DEO result DoubledExtendOkay 1
+Got LinkageError on GD
+Got LinkageError on TA
+Ctor: doubled implement, type 1
+DoubledImplement one
+Got LinkageError on DI (early)
+Got LinkageError on IDI (early)
diff --git a/test/068-classloader/info.txt b/test/068-classloader/info.txt
new file mode 100644
index 0000000..421e52a
--- /dev/null
+++ b/test/068-classloader/info.txt
@@ -0,0 +1,8 @@
+Class loaders allow code to "redefine" a given class, e.g. it's possible to
+have multiple classes called "com.android.Blah" loaded simultaneously. The
+classes are distinct and must be treated as such. This test exercises
+some situations in which a VM that only checks the UTF-8 signatures could
+mix things up.
+
+This also tests a couple of situations in which an IllegalAccessException
+is expected.
diff --git a/test/068-classloader/src-ex/AbstractGet.java b/test/068-classloader/src-ex/AbstractGet.java
new file mode 100644
index 0000000..db13b32
--- /dev/null
+++ b/test/068-classloader/src-ex/AbstractGet.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Verify that we don't reject this with a LinkageError.
+ */
+public class AbstractGet extends AbstractBase {
+ public DoubledExtendOkay getExtended() {
+ return new DoubledExtendOkay();
+ }
+}
+
+/**
+ * Abstract class, does not declare getAbstract. This cause the VM to
+ * generate a "miranda" method.
+ */
+abstract class AbstractBase extends BaseOkay {
+ public abstract DoubledExtendOkay getExtended();
+}
diff --git a/test/068-classloader/src-ex/DoubledExtend.java b/test/068-classloader/src-ex/DoubledExtend.java
new file mode 100644
index 0000000..6ad2708
--- /dev/null
+++ b/test/068-classloader/src-ex/DoubledExtend.java
@@ -0,0 +1,20 @@
+// Copyright 2008 The Android Open Source Project
+
+/**
+ * Doubled sub-class, form #2.
+ */
+public class DoubledExtend extends Base {
+ public DoubledExtend() {
+ //System.out.println("Ctor: doubled extend, type 2");
+ }
+
+ @Override
+ public DoubledExtend getExtended() {
+ //System.out.println("getExtended 2");
+ return new DoubledExtend();
+ }
+
+ public String getStr() {
+ return "DoubledExtend 2";
+ }
+}
diff --git a/test/068-classloader/src-ex/DoubledExtendOkay.java b/test/068-classloader/src-ex/DoubledExtendOkay.java
new file mode 100644
index 0000000..9674875
--- /dev/null
+++ b/test/068-classloader/src-ex/DoubledExtendOkay.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * "Okay" doubled sub-class, form #2.
+ */
+public class DoubledExtendOkay extends BaseOkay {
+ public DoubledExtendOkay() {
+ //System.out.println("Ctor: doubled extend okay, type 2");
+ }
+
+ /*
+ @Override
+ public DoubledExtendOkay getExtended() {
+ //System.out.println("getExtended 2");
+ return new DoubledExtendOkay();
+ }
+ */
+
+ public String getStr() {
+ return "DoubledExtendOkay 2";
+ }
+}
diff --git a/test/068-classloader/src-ex/DoubledImplement.java b/test/068-classloader/src-ex/DoubledImplement.java
new file mode 100644
index 0000000..5c44fc3
--- /dev/null
+++ b/test/068-classloader/src-ex/DoubledImplement.java
@@ -0,0 +1,18 @@
+// Copyright 2008 The Android Open Source Project
+
+/**
+ * Doubled sub-class, form #2.
+ */
+public class DoubledImplement implements ICommon {
+ public DoubledImplement() {
+ System.out.println("Ctor: doubled implement, type 2");
+ }
+
+ public DoubledImplement getDoubledInstance() {
+ return new DoubledImplement();
+ }
+
+ public void two() {
+ System.out.println("DoubledImplement two");
+ }
+}
diff --git a/test/068-classloader/src-ex/DoubledImplement2.java b/test/068-classloader/src-ex/DoubledImplement2.java
new file mode 100644
index 0000000..24ecb65
--- /dev/null
+++ b/test/068-classloader/src-ex/DoubledImplement2.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Another doubled sub-class, form #2.
+ */
+public class DoubledImplement2 implements ICommon2 {
+ public DoubledImplement2() {
+ System.out.println("Ctor: doubled implement, type 2");
+ }
+
+ public DoubledImplement2 getDoubledInstance2() {
+ return new DoubledImplement2();
+ }
+
+ public void two() {
+ System.out.println("DoubledImplement2 two");
+ }
+}
diff --git a/test/068-classloader/src-ex/GetDoubled.java b/test/068-classloader/src-ex/GetDoubled.java
new file mode 100644
index 0000000..28ada1e
--- /dev/null
+++ b/test/068-classloader/src-ex/GetDoubled.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * The interface we implement was declared in a different class loader,
+ * which means the DoubledExtend we return is not the one it was declared
+ * to return.
+ */
+public class GetDoubled implements IGetDoubled {
+ public DoubledExtendOkay getDoubled() {
+ return new DoubledExtendOkay();
+ }
+}
diff --git a/test/068-classloader/src-ex/IfaceImpl.java b/test/068-classloader/src-ex/IfaceImpl.java
new file mode 100644
index 0000000..7e9c27d
--- /dev/null
+++ b/test/068-classloader/src-ex/IfaceImpl.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class IfaceImpl implements IfaceSub {
+ public DoubledImplement2 getDoubledInstance2() {
+ return new DoubledImplement2();
+ }
+}
diff --git a/test/068-classloader/src-ex/IfaceSub.java b/test/068-classloader/src-ex/IfaceSub.java
new file mode 100644
index 0000000..7e512e7
--- /dev/null
+++ b/test/068-classloader/src-ex/IfaceSub.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public interface IfaceSub extends IfaceSuper {
+ public DoubledImplement2 getDoubledInstance2();
+}
diff --git a/test/068-classloader/src-ex/Inaccessible1.java b/test/068-classloader/src-ex/Inaccessible1.java
new file mode 100644
index 0000000..415a8a1
--- /dev/null
+++ b/test/068-classloader/src-ex/Inaccessible1.java
@@ -0,0 +1,11 @@
+// Copyright 2008 The Android Open Source Project
+
+/**
+ * Non-public class, inaccessible from Main. Note the constructor is
+ * public.
+ */
+class Inaccessible1 extends SimpleBase {
+ public Inaccessible1() {
+ System.out.println("--- inaccessible1");
+ }
+}
diff --git a/test/068-classloader/src-ex/Inaccessible2.java b/test/068-classloader/src-ex/Inaccessible2.java
new file mode 100644
index 0000000..dc20c21
--- /dev/null
+++ b/test/068-classloader/src-ex/Inaccessible2.java
@@ -0,0 +1,10 @@
+// Copyright 2008 The Android Open Source Project
+
+/**
+ * Public class that can't access its base.
+ */
+public class Inaccessible2 extends InaccessibleBase {
+ public Inaccessible2() {
+ System.out.println("--- inaccessible2");
+ }
+}
diff --git a/test/068-classloader/src-ex/Inaccessible3.java b/test/068-classloader/src-ex/Inaccessible3.java
new file mode 100644
index 0000000..771d0f7
--- /dev/null
+++ b/test/068-classloader/src-ex/Inaccessible3.java
@@ -0,0 +1,10 @@
+// Copyright 2008 The Android Open Source Project
+
+/**
+ * Public class that can't access its interface.
+ */
+public class Inaccessible3 implements InaccessibleInterface {
+ public Inaccessible3() {
+ System.out.println("--- inaccessible3");
+ }
+}
diff --git a/test/068-classloader/src/Base.java b/test/068-classloader/src/Base.java
new file mode 100644
index 0000000..b297a8a
--- /dev/null
+++ b/test/068-classloader/src/Base.java
@@ -0,0 +1,16 @@
+// Copyright 2008 The Android Open Source Project
+
+/**
+ * Common base class.
+ */
+public class Base {
+ public Base() {}
+
+ public DoubledExtend getExtended() {
+ return new DoubledExtend();
+ }
+
+ public static String doStuff(DoubledExtend dt) {
+ return dt.getStr();
+ }
+}
diff --git a/test/068-classloader/src/BaseOkay.java b/test/068-classloader/src/BaseOkay.java
new file mode 100644
index 0000000..48b7796
--- /dev/null
+++ b/test/068-classloader/src/BaseOkay.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Common base class.
+ */
+public class BaseOkay implements IDoubledExtendOkay {
+ public BaseOkay() {}
+
+ public DoubledExtendOkay getExtended() {
+ return new DoubledExtendOkay();
+ }
+
+ public static String doStuff(DoubledExtendOkay dt) {
+ return dt.getStr();
+ }
+}
+
+/**
+ * Interface that declares the not-overridden method. This exists to ensure
+ * that the existence of an interface doesn't trip the check.
+ */
+interface IDoubledExtendOkay {
+ public DoubledExtendOkay getExtended();
+}
diff --git a/test/068-classloader/src/DoubledExtend.java b/test/068-classloader/src/DoubledExtend.java
new file mode 100644
index 0000000..5f8ebc2
--- /dev/null
+++ b/test/068-classloader/src/DoubledExtend.java
@@ -0,0 +1,20 @@
+// Copyright 2008 The Android Open Source Project
+
+/**
+ * Doubled sub-class, form #1.
+ */
+public class DoubledExtend extends Base {
+ public DoubledExtend() {
+ //System.out.println("Ctor: doubled extend, type 1");
+ }
+
+ @Override
+ public DoubledExtend getExtended() {
+ System.out.println("getExtended 1");
+ return new DoubledExtend();
+ }
+
+ public String getStr() {
+ return "DoubledExtend 1";
+ }
+}
diff --git a/test/068-classloader/src/DoubledExtendOkay.java b/test/068-classloader/src/DoubledExtendOkay.java
new file mode 100644
index 0000000..e226e5f
--- /dev/null
+++ b/test/068-classloader/src/DoubledExtendOkay.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * "Okay" doubled sub-class, form #1.
+ */
+public class DoubledExtendOkay extends BaseOkay {
+ public DoubledExtendOkay() {
+ //System.out.println("Ctor: doubled extend okay, type 1");
+ }
+
+ /*
+ @Override
+ public DoubledExtendOkay getExtended() {
+ System.out.println("getExtended 1");
+ return new DoubledExtendOkay();
+ }
+ */
+
+ public String getStr() {
+ return "DoubledExtendOkay 1";
+ }
+}
diff --git a/test/068-classloader/src/DoubledImplement.java b/test/068-classloader/src/DoubledImplement.java
new file mode 100644
index 0000000..64ec5e2
--- /dev/null
+++ b/test/068-classloader/src/DoubledImplement.java
@@ -0,0 +1,18 @@
+// Copyright 2008 The Android Open Source Project
+
+/**
+ * Doubled sub-class, form #1.
+ */
+class DoubledImplement implements ICommon {
+ public DoubledImplement() {
+ System.out.println("Ctor: doubled implement, type 1");
+ }
+
+ public DoubledImplement getDoubledInstance() {
+ return new DoubledImplement();
+ }
+
+ public void one() {
+ System.out.println("DoubledImplement one");
+ }
+}
diff --git a/test/068-classloader/src/DoubledImplement2.java b/test/068-classloader/src/DoubledImplement2.java
new file mode 100644
index 0000000..12c036c
--- /dev/null
+++ b/test/068-classloader/src/DoubledImplement2.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Another doubled sub-class, form #1.
+ */
+public class DoubledImplement2 implements ICommon2 {
+ public DoubledImplement2() {
+ System.out.println("Ctor: doubled implement, type 1");
+ }
+
+ public DoubledImplement2 getDoubledInstance2() {
+ return new DoubledImplement2();
+ }
+
+ public void one() {
+ System.out.println("DoubledImplement2 one");
+ }
+}
diff --git a/test/068-classloader/src/FancyLoader.java b/test/068-classloader/src/FancyLoader.java
new file mode 100644
index 0000000..173b08f
--- /dev/null
+++ b/test/068-classloader/src/FancyLoader.java
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * A class loader with atypical behavior: we try to load a private
+ * class implementation before asking the system or boot loader. This
+ * is used to create multiple classes with identical names in a single VM.
+ *
+ * If DexFile is available, we use that; if not, we assume we're not in
+ * Dalvik and instantiate the class with defineClass().
+ *
+ * The location of the DEX files and class data is dependent upon the
+ * test framework.
+ */
+public class FancyLoader extends ClassLoader {
+ /* this is where the "alternate" .class files live */
+ static final String CLASS_PATH = "classes-ex/";
+
+ /* this is the "alternate" DEX/Jar file */
+ static final String DEX_FILE = "test-ex.jar";
+
+ /* on Dalvik, this is a DexFile; otherwise, it's null */
+ private Class mDexClass;
+
+ private Object mDexFile;
+
+ /**
+ * Construct FancyLoader, grabbing a reference to the DexFile class
+ * if we're running under Dalvik.
+ */
+ public FancyLoader(ClassLoader parent) {
+ super(parent);
+
+ try {
+ mDexClass = parent.loadClass("dalvik/system/DexFile");
+ } catch (ClassNotFoundException cnfe) {
+ // ignore -- not running Dalvik
+ }
+ }
+
+ /**
+ * Finds the class with the specified binary name.
+ *
+ * We search for a file in CLASS_PATH or pull an entry from DEX_FILE.
+ * If we don't find a match, we throw an exception.
+ */
+ protected Class<?> findClass(String name) throws ClassNotFoundException
+ {
+ if (mDexClass != null) {
+ return findClassDalvik(name);
+ } else {
+ return findClassNonDalvik(name);
+ }
+ }
+
+ /**
+ * Finds the class with the specified binary name, from a DEX file.
+ */
+ private Class<?> findClassDalvik(String name)
+ throws ClassNotFoundException {
+
+ if (mDexFile == null) {
+ synchronized (FancyLoader.class) {
+ Constructor ctor;
+ /*
+ * Construct a DexFile object through reflection.
+ */
+ try {
+ ctor = mDexClass.getConstructor(new Class[] {String.class});
+ } catch (NoSuchMethodException nsme) {
+ throw new ClassNotFoundException("getConstructor failed",
+ nsme);
+ }
+
+ try {
+ mDexFile = ctor.newInstance(DEX_FILE);
+ } catch (InstantiationException ie) {
+ throw new ClassNotFoundException("newInstance failed", ie);
+ } catch (IllegalAccessException iae) {
+ throw new ClassNotFoundException("newInstance failed", iae);
+ } catch (InvocationTargetException ite) {
+ throw new ClassNotFoundException("newInstance failed", ite);
+ }
+ }
+ }
+
+ /*
+ * Call DexFile.loadClass(String, ClassLoader).
+ */
+ Method meth;
+
+ try {
+ meth = mDexClass.getMethod("loadClass",
+ new Class[] { String.class, ClassLoader.class });
+ } catch (NoSuchMethodException nsme) {
+ throw new ClassNotFoundException("getMethod failed", nsme);
+ }
+
+ try {
+ meth.invoke(mDexFile, name, this);
+ } catch (IllegalAccessException iae) {
+ throw new ClassNotFoundException("loadClass failed", iae);
+ } catch (InvocationTargetException ite) {
+ throw new ClassNotFoundException("loadClass failed",
+ ite.getCause());
+ }
+
+ return null;
+ }
+
+ /**
+ * Finds the class with the specified binary name, from .class files.
+ */
+ private Class<?> findClassNonDalvik(String name)
+ throws ClassNotFoundException {
+
+ String pathName = CLASS_PATH + name + ".class";
+ //System.out.println("--- Fancy: looking for " + pathName);
+
+ File path = new File(pathName);
+ RandomAccessFile raf;
+
+ try {
+ raf = new RandomAccessFile(path, "r");
+ } catch (FileNotFoundException fnfe) {
+ throw new ClassNotFoundException("Not found: " + pathName);
+ }
+
+ /* read the entire file in */
+ byte[] fileData;
+ try {
+ fileData = new byte[(int) raf.length()];
+ raf.readFully(fileData);
+ } catch (IOException ioe) {
+ throw new ClassNotFoundException("Read error: " + pathName);
+ } finally {
+ try {
+ raf.close();
+ } catch (IOException ioe) {
+ // drop
+ }
+ }
+
+ /* create the class */
+ //System.out.println("--- Fancy: defining " + name);
+ try {
+ return defineClass(name, fileData, 0, fileData.length);
+ } catch (Throwable th) {
+ throw new ClassNotFoundException("defineClass failed", th);
+ }
+ }
+
+ /**
+ * Load a class.
+ *
+ * Normally a class loader wouldn't override this, but we want our
+ * version of the class to take precedence over an already-loaded
+ * version.
+ *
+ * We still want the system classes (e.g. java.lang.Object) from the
+ * bootstrap class loader.
+ */
+ protected Class<?> loadClass(String name, boolean resolve)
+ throws ClassNotFoundException
+ {
+ Class res;
+
+ /*
+ * 1. Invoke findLoadedClass(String) to check if the class has
+ * already been loaded.
+ *
+ * This doesn't change.
+ */
+ res = findLoadedClass(name);
+ if (res != null) {
+ System.out.println("FancyLoader.loadClass: "
+ + name + " already loaded");
+ if (resolve)
+ resolveClass(res);
+ return res;
+ }
+
+ /*
+ * 3. Invoke the findClass(String) method to find the class.
+ */
+ try {
+ res = findClass(name);
+ if (resolve)
+ resolveClass(res);
+ }
+ catch (ClassNotFoundException e) {
+ // we couldn't find it, so eat the exception and keep going
+ }
+
+ /*
+ * 2. Invoke the loadClass method on the parent class loader. If
+ * the parent loader is null the class loader built-in to the
+ * virtual machine is used, instead.
+ *
+ * (Since we're not in java.lang, we can't actually invoke the
+ * parent's loadClass() method, but we passed our parent to the
+ * super-class which can take care of it for us.)
+ */
+ res = super.loadClass(name, resolve); // returns class or throws
+ return res;
+ }
+}
diff --git a/test/068-classloader/src/ICommon.java b/test/068-classloader/src/ICommon.java
new file mode 100644
index 0000000..35a98cc
--- /dev/null
+++ b/test/068-classloader/src/ICommon.java
@@ -0,0 +1,8 @@
+// Copyright 2008 The Android Open Source Project
+
+/**
+ * Common interface.
+ */
+public interface ICommon {
+ public DoubledImplement getDoubledInstance();
+}
diff --git a/test/068-classloader/src/ICommon2.java b/test/068-classloader/src/ICommon2.java
new file mode 100644
index 0000000..6d81afc
--- /dev/null
+++ b/test/068-classloader/src/ICommon2.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Common interface.
+ */
+public interface ICommon2 {
+ public DoubledImplement2 getDoubledInstance2();
+}
diff --git a/test/068-classloader/src/IGetDoubled.java b/test/068-classloader/src/IGetDoubled.java
new file mode 100644
index 0000000..08cd1ce
--- /dev/null
+++ b/test/068-classloader/src/IGetDoubled.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Interface, loaded from one loader, used from another.
+ */
+public interface IGetDoubled {
+ public DoubledExtendOkay getDoubled();
+}
diff --git a/test/068-classloader/src/IfaceSuper.java b/test/068-classloader/src/IfaceSuper.java
new file mode 100644
index 0000000..36d278c
--- /dev/null
+++ b/test/068-classloader/src/IfaceSuper.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public interface IfaceSuper {
+ public DoubledImplement2 getDoubledInstance2();
+}
diff --git a/test/068-classloader/src/InaccessibleBase.java b/test/068-classloader/src/InaccessibleBase.java
new file mode 100644
index 0000000..83af665
--- /dev/null
+++ b/test/068-classloader/src/InaccessibleBase.java
@@ -0,0 +1,7 @@
+// Copyright 2008 The Android Open Source Project
+
+/**
+ * Non-public base class, inaccessible from alternate class loader.
+ */
+class InaccessibleBase {
+}
diff --git a/test/068-classloader/src/InaccessibleInterface.java b/test/068-classloader/src/InaccessibleInterface.java
new file mode 100644
index 0000000..7f52b80
--- /dev/null
+++ b/test/068-classloader/src/InaccessibleInterface.java
@@ -0,0 +1,7 @@
+// Copyright 2008 The Android Open Source Project
+
+/**
+ * Non-public interface class, inaccessible from alternate class loader.
+ */
+interface InaccessibleInterface {
+}
diff --git a/test/068-classloader/src/Main.java b/test/068-classloader/src/Main.java
new file mode 100644
index 0000000..1bc7b04
--- /dev/null
+++ b/test/068-classloader/src/Main.java
@@ -0,0 +1,425 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Class loader test.
+ */
+public class Main {
+ /**
+ * Main entry point.
+ */
+ public static void main(String[] args) {
+ FancyLoader loader;
+
+ loader = new FancyLoader(ClassLoader.getSystemClassLoader());
+ //System.out.println("SYSTEM: " + ClassLoader.getSystemClassLoader());
+ //System.out.println("ALTERN: " + loader);
+
+ /*
+ * This statement has no effect on this program, but it can
+ * change the point where a LinkageException is thrown in
+ * testImplement(). When this is present the "reference
+ * implementation" throws an exception from Class.newInstance(),
+ * when it's absent the exception is deferred until the first time
+ * we call a method that isn't actually implemented.
+ *
+ * This isn't the class that fails -- it's a class with the same
+ * name in the "fancy" class loader -- but the VM thinks it has a
+ * reference to one of these; presumably the difference is that
+ * without this the VM finds itself holding a reference to an
+ * instance of an uninitialized class.
+ */
+ System.out.println("base: " + DoubledImplement.class);
+ System.out.println("base2: " + DoubledImplement2.class);
+
+ /*
+ * Run tests.
+ */
+ testAccess1(loader);
+ testAccess2(loader);
+ testAccess3(loader);
+
+ testExtend(loader);
+ testExtendOkay(loader);
+ testInterface(loader);
+ testAbstract(loader);
+ testImplement(loader);
+ testIfaceImplement(loader);
+ }
+
+ /**
+ * See if we can load a class that isn't public to us. We should be
+ * able to load it but not instantiate it.
+ */
+ static void testAccess1(ClassLoader loader) {
+ Class altClass;
+
+ try {
+ altClass = loader.loadClass("Inaccessible1");
+ } catch (ClassNotFoundException cnfe) {
+ System.err.println("loadClass failed");
+ cnfe.printStackTrace();
+ return;
+ }
+
+ /* instantiate */
+ Object obj;
+ try {
+ obj = altClass.newInstance();
+ System.err.println("ERROR: Inaccessible1 was accessible");
+ } catch (InstantiationException ie) {
+ System.err.println("newInstance failed: " + ie);
+ return;
+ } catch (IllegalAccessException iae) {
+ System.out.println("Got expected access exception #1");
+ //System.out.println("+++ " + iae);
+ return;
+ }
+ }
+
+ /**
+ * See if we can load a class whose base class is not accessible to it
+ * (though the base *is* accessible to us).
+ */
+ static void testAccess2(ClassLoader loader) {
+ Class altClass;
+
+ try {
+ altClass = loader.loadClass("Inaccessible2");
+ System.err.println("ERROR: Inaccessible2 was accessible");
+ } catch (ClassNotFoundException cnfe) {
+ Throwable cause = cnfe.getCause();
+ if (cause instanceof IllegalAccessError) {
+ System.out.println("Got expected CNFE/IAE #2");
+ } else {
+ System.err.println("Got unexpected CNFE/IAE #2");
+ cnfe.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * See if we can load a class with an inaccessible interface.
+ */
+ static void testAccess3(ClassLoader loader) {
+ Class altClass;
+
+ try {
+ altClass = loader.loadClass("Inaccessible3");
+ System.err.println("ERROR: Inaccessible3 was accessible");
+ } catch (ClassNotFoundException cnfe) {
+ Throwable cause = cnfe.getCause();
+ if (cause instanceof IllegalAccessError) {
+ System.out.println("Got expected CNFE/IAE #3");
+ } else {
+ System.err.println("Got unexpected CNFE/IAE #3");
+ cnfe.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * Test a doubled class that extends the base class.
+ */
+ static void testExtend(ClassLoader loader) {
+ Class doubledExtendClass;
+ Object obj;
+
+ /* get the "alternate" version of DoubledExtend */
+ try {
+ doubledExtendClass = loader.loadClass("DoubledExtend");
+ //System.out.println("+++ DoubledExtend is " + doubledExtendClass
+ // + " in " + doubledExtendClass.getClassLoader());
+ } catch (ClassNotFoundException cnfe) {
+ System.err.println("loadClass failed: " + cnfe);
+ return;
+ }
+
+ /* instantiate */
+ try {
+ obj = doubledExtendClass.newInstance();
+ } catch (InstantiationException ie) {
+ System.err.println("newInstance failed: " + ie);
+ return;
+ } catch (IllegalAccessException iae) {
+ System.err.println("newInstance failed: " + iae);
+ return;
+ } catch (LinkageError le) {
+ System.out.println("Got expected LinkageError on DE");
+ return;
+ }
+
+ /* use the base class reference to get a CL-specific instance */
+ Base baseRef = (Base) obj;
+ DoubledExtend de = baseRef.getExtended();
+
+ /* try to call through it */
+ try {
+ String result;
+
+ result = Base.doStuff(de);
+ System.err.println("ERROR: did not get LinkageError on DE");
+ System.err.println("(result=" + result + ")");
+ } catch (LinkageError le) {
+ System.out.println("Got expected LinkageError on DE");
+ return;
+ }
+ }
+
+ /**
+ * Test a doubled class that extends the base class, but is okay since
+ * it doesn't override the base class method.
+ */
+ static void testExtendOkay(ClassLoader loader) {
+ Class doubledExtendOkayClass;
+ Object obj;
+
+ /* get the "alternate" version of DoubledExtendOkay */
+ try {
+ doubledExtendOkayClass = loader.loadClass("DoubledExtendOkay");
+ } catch (ClassNotFoundException cnfe) {
+ System.err.println("loadClass failed: " + cnfe);
+ return;
+ }
+
+ /* instantiate */
+ try {
+ obj = doubledExtendOkayClass.newInstance();
+ } catch (InstantiationException ie) {
+ System.err.println("newInstance failed: " + ie);
+ return;
+ } catch (IllegalAccessException iae) {
+ System.err.println("newInstance failed: " + iae);
+ return;
+ } catch (LinkageError le) {
+ System.err.println("Got unexpected LinkageError on DEO");
+ le.printStackTrace();
+ return;
+ }
+
+ /* use the base class reference to get a CL-specific instance */
+ BaseOkay baseRef = (BaseOkay) obj;
+ DoubledExtendOkay de = baseRef.getExtended();
+
+ /* try to call through it */
+ try {
+ String result;
+
+ result = BaseOkay.doStuff(de);
+ System.out.println("Got DEO result " + result);
+ } catch (LinkageError le) {
+ System.err.println("Got unexpected LinkageError on DEO");
+ le.printStackTrace();
+ return;
+ }
+ }
+
+ /**
+ * Try to access a doubled class through a class that implements
+ * an interface declared in a different class.
+ */
+ static void testInterface(ClassLoader loader) {
+ Class getDoubledClass;
+ Object obj;
+
+ /* get GetDoubled from the "alternate" class loader */
+ try {
+ getDoubledClass = loader.loadClass("GetDoubled");
+ } catch (ClassNotFoundException cnfe) {
+ System.err.println("loadClass failed: " + cnfe);
+ return;
+ }
+
+ /* instantiate */
+ try {
+ obj = getDoubledClass.newInstance();
+ } catch (InstantiationException ie) {
+ System.err.println("newInstance failed: " + ie);
+ return;
+ } catch (IllegalAccessException iae) {
+ System.err.println("newInstance failed: " + iae);
+ return;
+ } catch (LinkageError le) {
+ // Dalvik bails here
+ System.out.println("Got LinkageError on GD");
+ return;
+ }
+
+ /*
+ * Cast the object to the interface, and try to use it.
+ */
+ IGetDoubled iface = (IGetDoubled) obj;
+ try {
+ /* "de" will be the wrong variety of DoubledExtendOkay */
+ DoubledExtendOkay de = iface.getDoubled();
+ // reference impl bails here
+ String str = de.getStr();
+ } catch (LinkageError le) {
+ System.out.println("Got LinkageError on GD");
+ return;
+ }
+ System.err.println("Should have failed by now on GetDoubled");
+ }
+
+ /**
+ * Throw an abstract class into the middle and see what happens.
+ */
+ static void testAbstract(ClassLoader loader) {
+ Class abstractGetClass;
+ Object obj;
+
+ /* get AbstractGet from the "alternate" loader */
+ try {
+ abstractGetClass = loader.loadClass("AbstractGet");
+ } catch (ClassNotFoundException cnfe) {
+ System.err.println("loadClass ta failed: " + cnfe);
+ return;
+ }
+
+ /* instantiate */
+ try {
+ obj = abstractGetClass.newInstance();
+ } catch (InstantiationException ie) {
+ System.err.println("newInstance failed: " + ie);
+ return;
+ } catch (IllegalAccessException iae) {
+ System.err.println("newInstance failed: " + iae);
+ return;
+ } catch (LinkageError le) {
+ System.out.println("Got LinkageError on TA");
+ return;
+ }
+
+ /* use the base class reference to get a CL-specific instance */
+ BaseOkay baseRef = (BaseOkay) obj;
+ DoubledExtendOkay de = baseRef.getExtended();
+
+ /* try to call through it */
+ try {
+ String result;
+
+ result = BaseOkay.doStuff(de);
+ } catch (LinkageError le) {
+ System.out.println("Got LinkageError on TA");
+ return;
+ }
+ System.err.println("Should have failed by now in testAbstract");
+ }
+
+ /**
+ * Test a doubled class that implements a common interface.
+ */
+ static void testImplement(ClassLoader loader) {
+ Class doubledImplementClass;
+ Object obj;
+
+ useImplement(new DoubledImplement(), true);
+
+ /* get the "alternate" version of DoubledImplement */
+ try {
+ doubledImplementClass = loader.loadClass("DoubledImplement");
+ } catch (ClassNotFoundException cnfe) {
+ System.err.println("loadClass failed: " + cnfe);
+ return;
+ }
+
+ /* instantiate */
+ try {
+ obj = doubledImplementClass.newInstance();
+ } catch (InstantiationException ie) {
+ System.err.println("newInstance failed: " + ie);
+ return;
+ } catch (IllegalAccessException iae) {
+ System.err.println("newInstance failed: " + iae);
+ return;
+ } catch (LinkageError le) {
+ System.out.println("Got LinkageError on DI (early)");
+ return;
+ }
+
+ /* if we lived this long, try to do something with it */
+ ICommon icommon = (ICommon) obj;
+ useImplement(icommon.getDoubledInstance(), false);
+ }
+
+ /**
+ * Do something with a DoubledImplement instance.
+ */
+ static void useImplement(DoubledImplement di, boolean isOne) {
+ //System.out.println("useObject: " + di.toString() + " -- "
+ // + di.getClass().getClassLoader());
+ try {
+ di.one();
+ if (!isOne) {
+ System.err.println("ERROR: did not get LinkageError on DI");
+ }
+ } catch (LinkageError le) {
+ if (!isOne) {
+ System.out.println("Got LinkageError on DI (late)");
+ } else {
+ throw le;
+ }
+ }
+ }
+
+
+ /**
+ * Test a class that implements an interface with a super-interface
+ * that refers to a doubled class.
+ */
+ static void testIfaceImplement(ClassLoader loader) {
+ Class ifaceImplClass;
+ Object obj;
+
+ /*
+ * Create an instance of IfaceImpl. We also pull in
+ * DoubledImplement2 from the other class loader; without this
+ * we don't fail in some implementations.
+ */
+ try {
+ ifaceImplClass = loader.loadClass("IfaceImpl");
+ ifaceImplClass = loader.loadClass("DoubledImplement2");
+ } catch (ClassNotFoundException cnfe) {
+ System.err.println("loadClass failed: " + cnfe);
+ return;
+ }
+
+ /* instantiate */
+ try {
+ obj = ifaceImplClass.newInstance();
+ } catch (InstantiationException ie) {
+ System.err.println("newInstance failed: " + ie);
+ return;
+ } catch (IllegalAccessException iae) {
+ System.err.println("newInstance failed: " + iae);
+ return;
+ } catch (LinkageError le) {
+ System.out.println("Got LinkageError on IDI (early)");
+ //System.out.println(le);
+ return;
+ }
+
+ /*
+ * Without the pre-load of FancyLoader->DoubledImplement2, some
+ * implementations will happily execute through this part. "obj"
+ * comes from FancyLoader, but the di2 returned from ifaceSuper
+ * comes from the application class loader.
+ */
+ IfaceSuper ifaceSuper = (IfaceSuper) obj;
+ DoubledImplement2 di2 = ifaceSuper.getDoubledInstance2();
+ di2.one();
+ }
+}
diff --git a/test/068-classloader/src/SimpleBase.java b/test/068-classloader/src/SimpleBase.java
new file mode 100644
index 0000000..fd56db9
--- /dev/null
+++ b/test/068-classloader/src/SimpleBase.java
@@ -0,0 +1,8 @@
+// Copyright 2008 The Android Open Source Project
+
+/**
+ * Simple, public base class.
+ */
+public class SimpleBase {
+ public SimpleBase() {}
+}
diff --git a/test/068-classloader/src/Useless.java b/test/068-classloader/src/Useless.java
new file mode 100644
index 0000000..f51d9a8
--- /dev/null
+++ b/test/068-classloader/src/Useless.java
@@ -0,0 +1,4 @@
+
+public class Useless implements ICommon {
+ public DoubledImplement getDoubledInstance() { return null; }
+}