diff options
author | 2013-02-22 23:29:00 -0800 | |
---|---|---|
committer | 2013-02-25 08:54:25 -0800 | |
commit | 530f71c040cb1a7b946d5566d5a746f08f2d082c (patch) | |
tree | b350413f9cccdac06730518a9ad2eb7ef8a6f083 | |
parent | 5fe2c162a422426687ba3570df1dc68864386764 (diff) |
Fix proxy return ClassCastException and add test.
Add test for Bug: 8250775 that doesn't effect ART. Expand test case further.
ClassCastException has no constructor expecting a cause and so using this
creates a JNI failure. Switch to not using a wrapped exception as the wrapping
itself wasn't adding information.
Change-Id: I32dd541e1a1022089ec993fa4f4646042c5bf1fa
-rw-r--r-- | src/runtime_support.cc | 14 | ||||
-rw-r--r-- | test/044-proxy/expected.txt | 8 | ||||
-rw-r--r-- | test/044-proxy/src/Main.java | 1 | ||||
-rw-r--r-- | test/044-proxy/src/NarrowingTest.java | 67 |
4 files changed, 85 insertions, 5 deletions
diff --git a/src/runtime_support.cc b/src/runtime_support.cc index 84a19cf491..d76999c5e2 100644 --- a/src/runtime_support.cc +++ b/src/runtime_support.cc @@ -440,11 +440,15 @@ JValue InvokeProxyInvocationHandler(ScopedObjectAccessUnchecked& soa, const char mirror::Object* result_ref = soa.Decode<mirror::Object*>(result); bool unboxed_okay = UnboxPrimitiveForResult(result_ref, result_type, result_unboxed); if (!unboxed_okay) { - soa.Self()->ThrowNewWrappedException("Ljava/lang/ClassCastException;", - StringPrintf("Couldn't convert result of type %s to %s", - PrettyTypeOf(result_ref).c_str(), - PrettyDescriptor(result_type).c_str() - ).c_str()); + // UnboxPrimitiveForResult creates an IllegalArgumentException. Discard and create a + // meaningful ClassCastException. + DCHECK(soa.Self()->IsExceptionPending()); + soa.Self()->ClearException(); + soa.Self()->ThrowNewException("Ljava/lang/ClassCastException;", + StringPrintf("Couldn't convert result of type %s to %s", + PrettyTypeOf(result_ref).c_str(), + PrettyDescriptor(result_type).c_str() + ).c_str()); } return result_unboxed; } diff --git a/test/044-proxy/expected.txt b/test/044-proxy/expected.txt index 578fd971f3..eafaf1d188 100644 --- a/test/044-proxy/expected.txt +++ b/test/044-proxy/expected.txt @@ -82,3 +82,11 @@ Got expected exception Invoke public abstract void InterfaceW1.bothThrowBase() throws BaseException,SubException,SubSubException (no args) Got expected exception +Proxy methods: [public final boolean $Proxy7.equals(java.lang.Object), public final java.lang.Object $Proxy7.foo(), public final java.lang.String $Proxy7.foo(), public final int $Proxy7.hashCode(), public final java.lang.String $Proxy7.toString()] +Invocation of public abstract java.lang.String NarrowingTest$I2.foo() +Invoking foo using I2 type: hello +Invocation of public abstract java.lang.Object NarrowingTest$I1.foo() +Invoking foo using I1 type: 1 +Invocation of public abstract java.lang.String NarrowingTest$I2.foo() +Got expected exception +Proxy narrowed invocation return type passed diff --git a/test/044-proxy/src/Main.java b/test/044-proxy/src/Main.java index 5396ab8842..078569f121 100644 --- a/test/044-proxy/src/Main.java +++ b/test/044-proxy/src/Main.java @@ -26,5 +26,6 @@ public class Main { Clash3.main(null); Clash4.main(null); WrappedThrow.main(null); + NarrowingTest.main(null); } } diff --git a/test/044-proxy/src/NarrowingTest.java b/test/044-proxy/src/NarrowingTest.java new file mode 100644 index 0000000000..3b94b76279 --- /dev/null +++ b/test/044-proxy/src/NarrowingTest.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2011 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.lang.reflect.*; +import java.util.Arrays; + +class NarrowingTest { + + interface I1 { + public Object foo(); + } + + interface I2 extends I1 { + // Note that this method declaration narrows the return type. + @Override + public String foo(); + } + + public static void main(String[] args) { + I2 proxy = (I2) Proxy.newProxyInstance(NarrowingTest.class.getClassLoader(), + new Class<?>[] { I2.class }, + new InvocationHandler() { + int count = 0; + @Override + public Object invoke(Object proxy, Method method, + Object[] args) throws Throwable { + System.out.println("Invocation of " + method); + if (count == 0) { + count++; + return "hello"; + } else { + return Integer.valueOf(1); + } + } + }); + + Method[] methods = proxy.getClass().getDeclaredMethods(); + System.out.println("Proxy methods: " + Arrays.deepToString(methods)); + + System.out.println("Invoking foo using I2 type: " + proxy.foo()); + + I1 proxyAsParent = proxy; + System.out.println("Invoking foo using I1 type: " + proxyAsParent.foo()); + + try { + proxy.foo(); + System.out.println("Didn't get expected exception"); + } catch (ClassCastException e) { + // With an I2 invocation returning an integer is an exception. + System.out.println("Got expected exception"); + } + + System.out.println("Proxy narrowed invocation return type passed"); + } +} |