Proposal: java.lang.reflect.Proxy and default methods
Steven Schlansker
stevenschlansker at gmail.com
Thu Jun 16 20:10:55 UTC 2016
> On Jun 16, 2016, at 12:29 PM, Mandy Chung <mandy.chung at oracle.com> wrote:
>
> Can you elaborate how proxy and default methods affects your library to able to run with security manager?
So in this particular case, I wanted to create an interface type where some methods are automatically generated
from declarative annotations and some are not.
interface MyDao {
@SqlQuery("SELECT count(1) FROM table WHERE state='foo'")
int getFooCount();
@SqlQuery("SELECT count(1) FROM table WHERE state='bar'")
int getBarCount();
@InTransaction
default getFooAndBarCount() {
return getFooCount() + getBarCount();
}
}
Another use case I have, generating configuration beans from properties:
interface SomeConfig {
@Config("key.a")
int getA(); // required
@Config("key.b")
default int getB() {
return 3; // a nice way to specify the default value
}
}
Neither of these are impossible to work around. But I think the list of situations
where this is useful is long and mostly not explored because it is very hard
to do so today :)
(Specifically about the security manager comment, I am using the workaround outlined
in this thread which involves calling setAccessible on the MethodHandle constructor
to avoid the unreflectSpecial security check.)
>
> This is a good enhancement. I have created a JBS issue to track that [1]. There is no such existing enhancement request in JBS.
>
> Mandy
> [1] https://bugs.openjdk.java.net/browse/JDK-8159746
>
>> On Jun 16, 2016, at 11:14 AM, Steven Schlansker <stevenschlansker at gmail.com> wrote:
>>
>> Hi everyone,
>>
>> I am glad this was discussed on the list again.
>> I just wanted to throw out there, as a library developer and
>> end user, I now have had to reproduce this hack in no fewer
>> than four different projects for various reasons.
>>
>> It is even worse because it means that my library cannot run
>> under a SecurityManager. While this isn't a problem for me
>> personally it does limit the utility of any libraries I might produce.
>>
>> It really is a glaring missing API and if it does not make Java 9
>> I can't imagine I will be the only person that is extremely disappointed.
>>
>> Thanks,
>> Steven
>>
>>> On Jun 6, 2016, at 1:58 PM, Mandy Chung <mandy.chung at oracle.com> wrote:
>>>
>>> Hi Peter,
>>>
>>> Thanks for the proposal. This feature has been lacking. When this subject was brought, I also have similiar thought to provide a way in Proxy class for InvocationHandler to invoke a default method (but of course no time to put into it).
>>>
>>> I appreciate your contribution and good work. I support to add this feature in a future release.
>>>
>>> I personally don’t feel comfortable to absorb this small API targetting for JDK 9 (since I don’t have the cycle to shepherd this in the next few months). I may be overly conversative but I won’t take security assessment lightly. Maybe someone else is able to help you move this forward before I am available.
>>>
>>> Mandy
>>>
>>>> On Jun 3, 2016, at 7:58 AM, Peter Levart <peter.levart at gmail.com> wrote:
>>>>
>>>> Hi,
>>>>
>>>> Since Java SE 8 introduced default methods in interfaces there was a question what to do with java.lang.reflect.Proxy API. Nothing was done to the API at that time, so the default behavior is to proxy default methods too. InvocationHandler gets invoked for default methods, but it has not provision to forward such calls to the default implementations in the interfaces.
>>>>
>>>> I propose a simple API addition that allows calling super default methods in proxy instances:
>>>>
>>>> http://cr.openjdk.java.net/~plevart/jdk9-dev/Proxy.invokeSuperDefaults/webrev.02/
>>>>
>>>> With this addition one can simply decide in the InvocationHandler what to do with invocations to default methods and can forward such invocation to the default implementation:
>>>>
>>>> public class Test {
>>>>
>>>> interface I1 {
>>>> default void m() {
>>>> System.out.println(" default I1.m() called");
>>>> }
>>>> }
>>>>
>>>> interface I2 {
>>>> default void m() {
>>>> System.out.println(" default I2.m() called");
>>>> }
>>>> }
>>>>
>>>> interface I12 extends I1, I2 {
>>>> @Override
>>>> void m();
>>>>
>>>> default int sum(int a, int b) {
>>>> return a + b;
>>>> }
>>>>
>>>> default Object[] concat(Object first, Object... rest) {
>>>> Object[] result = new Object[1 + rest.length];
>>>> result[0] = first;
>>>> System.arraycopy(rest, 0, result, 1, rest.length);
>>>> return result;
>>>> }
>>>> }
>>>>
>>>> public static void main(String[] args) {
>>>>
>>>> InvocationHandler h = (proxy, method, params) -> {
>>>> System.out.println("\nInvocationHandler called for: " + method +
>>>> " with parameters: " + Arrays.toString(params));
>>>> if (method.isDefault()) {
>>>> try {
>>>> return Proxy.invokeSuper(proxy, method, params);
>>>> } catch (InvocationTargetException e) {
>>>> throw e.getCause();
>>>> }
>>>> } else {
>>>> switch (method.getName()) {
>>>> case "m":
>>>> System.out.println(" abstract I12.m(): called");
>>>> return null;
>>>> default:
>>>> throw new UnsupportedOperationException(
>>>> "Unsupported method: " + method);
>>>> }
>>>> }
>>>> };
>>>>
>>>> I1 i1 = (I1) Proxy.newProxyInstance(
>>>> I1.class.getClassLoader(), new Class<?>[]{I1.class}, h);
>>>> i1.m();
>>>>
>>>> I2 i2 = (I2) Proxy.newProxyInstance(
>>>> I2.class.getClassLoader(), new Class<?>[]{I2.class}, h);
>>>> i2.m();
>>>>
>>>> I12 i12 = (I12) Proxy.newProxyInstance(
>>>> I12.class.getClassLoader(), new Class<?>[]{I12.class}, h);
>>>> i12.m();
>>>>
>>>> System.out.println(" 1 + 2 = " + i12.sum(1, 2));
>>>> System.out.println(" [1] concat [2, 3, 4] = " +
>>>> Arrays.toString(i12.concat(1, 2, 3, 4)));
>>>> }
>>>> }
>>>>
>>>>
>>>> I know FC date is over, but this is really a small change and I have heard several people that such feature is missing from the Proxy API.
>>>>
>>>> I'm prepared to create jtreg tests covering the specification if this proposal is accepted.
>>>>
>>>> Regards, Peter
>>>>
>>>>
>>>>
>>>
>>
>
More information about the core-libs-dev
mailing list