From dev-return-4500-archive-asf-public=cust-asf.ponee.io@groovy.apache.org Sun Apr 1 18:34:03 2018 Return-Path: X-Original-To: archive-asf-public@cust-asf.ponee.io Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx-eu-01.ponee.io (Postfix) with SMTP id 32039180634 for ; Sun, 1 Apr 2018 18:34:03 +0200 (CEST) Received: (qmail 20561 invoked by uid 500); 1 Apr 2018 16:34:02 -0000 Mailing-List: contact dev-help@groovy.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@groovy.apache.org Delivered-To: mailing list dev@groovy.apache.org Received: (qmail 20547 invoked by uid 99); 1 Apr 2018 16:34:01 -0000 Received: from pnap-us-west-generic-nat.apache.org (HELO spamd3-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 01 Apr 2018 16:34:01 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd3-us-west.apache.org (ASF Mail Server at spamd3-us-west.apache.org) with ESMTP id 2CD4D180146 for ; Sun, 1 Apr 2018 16:34:01 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd3-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: -0.701 X-Spam-Level: X-Spam-Status: No, score=-0.701 tagged_above=-999 required=6.31 tests=[RCVD_IN_DNSWL_LOW=-0.7, SPF_PASS=-0.001] autolearn=disabled Received: from mx1-lw-eu.apache.org ([10.40.0.8]) by localhost (spamd3-us-west.apache.org [10.40.0.10]) (amavisd-new, port 10024) with ESMTP id sWXp7K10j8v0 for ; Sun, 1 Apr 2018 16:33:59 +0000 (UTC) Received: from mout.gmx.net (mout.gmx.net [212.227.17.20]) by mx1-lw-eu.apache.org (ASF Mail Server at mx1-lw-eu.apache.org) with ESMTPS id D0FA85F23D for ; Sun, 1 Apr 2018 16:33:58 +0000 (UTC) Received: from [192.168.1.4] ([89.14.130.138]) by mail.gmx.com (mrgmx103 [212.227.17.168]) with ESMTPSA (Nemesis) id 0M8mCe-1fEnvn3ZVs-00C89L for ; Sun, 01 Apr 2018 18:33:51 +0200 To: dev@groovy.incubator.apache.org From: Jochen Theodorou Subject: new MOP under Java9 module system findings Message-ID: <3d869294-595c-5e7e-fb5e-ebc43a6c67dc@gmx.org> Date: Sun, 1 Apr 2018 18:33:49 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.5.0 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 7bit X-Provags-ID: V03:K0:ZPRvVdL76BKIVmbg/pbhVTycILDZXFGNJKdz9IoPxZcaNU+IKhU viNUjm7aGbdz9jugzJ0yQSbfsScv400FIC/QbTEVw+nlXe2fuq6c7cOSMV2nRPLoJGiawna p3HIl5SvaJnn7huGCSRRP8rquXivNClR+Gi0c5KJKue15cfiwP9oULn3yhXR6+948cntVm0 sDiYdXXuBaQosjKZ7/RFg== X-UI-Out-Filterresults: notjunk:1;V01:K0:Qbj7OIAwuVQ=:+/nKswbupjeTkICskLAuqd eWNDGsvZRhK3byT5+B5wUl1tCTjDsk+TJyNj8/FjqFlgRdKorxOjdttT2uK3t3lVT1ZetQz4g 0obJ5aLkuvu1zYw+nMhTc4ceC3MCF9CYlGCnHbRh5mq3jmSvKa4PXhBrkIRp/kLu6fLYIfxJI uHOJP1aFOvSGVbEQTLNoBJ5B2xhTvQgI2UfP/8fRaCKrSl/jzsvkqGTPyvYVjsoH20qDa0fkB h1EKz2brpITT3iB2pxtk3YFTFcIM7C0AQyDOSI2YcvrOWbZHx84h9tAQJajQoUqvJTDPXniRp sfM53p6/5EoIzAD4p90p/AuAiQhONYfAagRaZUaw0mDXG8gQMhzoZ0Gr45u7Vz/+1Lmt+9Yqy 0aKqvr7DdzKCY7Ab8r9GYLcY63wKGOCRkt9dizIJryx2LpvxgxiHvKhdafD7dt96Q4/62WM6r 9QzABvpce+XCPZCcVdQNbzPHeGgzxVLc/mJdf9s/QPuPrFVbv3/Wk6/O5PQZSUHIv5FYr4D+4 G22RukbwLb/3OThRfUUAsESh0k5VlnC7TjfM7WFQej2lcs5NOgThGgApHp74yELbh+KEB5M8g nZ43q9RecYuRdvY/FyAnCALRZQXP+UjuxtAHTNmTOctnzqIcoIkeM5WmkCRCLJB73GSu/9o2j JO2sBdE4W4wfDlK4ZhJikJtj1Xtcw/gu4Oq/3gGV3LwtbrWoaHG15fuRYPILCghPP6bQcCuAR rttNtv7Ta3mJ2ZEaU2P0VX1rqG589Ov+9mgbSzbxONMBLyKcDnl8satGYz68XJ+H0Y60vFjXh o1Zu9PNEeodwmU1CLdgIa2HzKrn/zIx7SQAW5EFhoiFqJVfv6E= Hi all, yesterday I was playing around with java modules and tried to implement some pseudo mops based on what we have and I'd like to share my impressions. Please do not wonder that I only mention method invocation, I only played around with that. missingMethod seems to be easy to do, also builders based on missingMethod instead of invokeMethod will do in the form we have now. I managed to do that with a mini meta class, that uses reflection to inspect the class (no setAccessible). The bad part here is that the actual invocation will have to be using MethodHandles, which requires us to create them of course, which is not good for performance if we have to unreflect the methods. But a new meta class system could take care of that at the price of increasing the meta class creation time. But I think these problems can be solved. In my mini mop I was able to call private methods without helper methods and also from inner classes. But when I mention private methods I do mean methods we would have access to in Java as well. This is done by the class doing the call providing a Lookup object, which allows me to make calls on behalf of the caller class. Which means I can *not* call private methods from arbitrary classes. This means you will no longer be able to write unit tests in Groovy, able to tests private methods from Java classes... unless we preprocess the classes and make a lookup object available. For Groovy classes we could provide such a mechanism by default, but frankly I would not do that, because that lookup object means you can access all the internals of the class without restrictions and that without any security manager. The problem child in our current mop here is invokeMethod. methodMissing is at the end of the mop and while it does not matter there to loose the caller context we can keep them as is. But invokeMethod tends to be more in between there is a potential problem. As long as invokeMethod is for the current class, there is no trouble, but calling into a another class from invokeMethod means to use the context of the class invokeMethod is in and loosing the original context. Especially that logic to just call to meta class in invokeMethod is a problem. Example: class LogProxy { def orig def invokeMethod(String name, Object args) { println "called method $name" orig."$name"(*args) } } class Foo { def proxy = new LogProxy(orig:this) private method(){} def publicMethod() { proxy.method() } } This kind of code can work in Groovy, as long as we are not working on a subclass of Foo. To make this work with modules where LogProxy is from another module as Foo, I think the only way is to expose the lookup object and use that for the creation of the handle. But that means it has to be part of the call orig."$name"(*args) and of the method signature of invokeMethod. In summary I think all the cases where our mop methods operate as endpoints can be made work. But that means invokeMethod can no longer work as entry point and actually becomes the same as methodMissing, which begs the question if it should even exist. Similar cases can be made for get(String) and others. For invokeMethod as entry point to method invocation the signature would have to change to contain the Lookup object at least, and a way to invoke a method using that lookup object. bye Jochen