[cdi-dev] Proxy implementation leaks

Pete Muir pmuir at redhat.com
Mon May 9 11:32:46 EDT 2011


You can't enhance the class without either a javaagent or bytecode instr.

If you use subclassing you only need to call the ctor of the superclass once, not twice as it stands today.

On 9 May 2011, at 16:30, Mark Struberg wrote:

> was about to ask the same ;)
> 
> If there is some subclassing involved, then you will need to call the constructor of the superclass. You cannot solve this another way without changing the original class.
> 
> There is only one magic trick, but this is a pretty heavyweight one:
> 1.) dynamically create an interface with all the methods from the class hierarchy from the proxied class
> 2.) create a java.lang.reflect.proxy for the interface
> 3.) dynamically _change_ the original proxied class to additionally implement the freshly generated interface
> 
> This is pretty much work, but imo the only way which works.
> The downsides are that you need to 'enhance' the original class, which might cause ClassCastExceptions and lots of other nasty problems...
> 
> LieGrue,
> strub
> 
> --- On Mon, 5/9/11, Arne Limburg <arne.limburg at openknowledge.de> wrote:
> 
>> From: Arne Limburg <arne.limburg at openknowledge.de>
>> Subject: AW: [cdi-dev] Proxy implementation leaks
>> To: "Pete Muir" <pmuir at redhat.com>, "Mark Struberg" <struberg at yahoo.de>
>> Cc: "cdi-dev at lists.jboss.org" <cdi-dev at lists.jboss.org>
>> Date: Monday, May 9, 2011, 3:26 PM
>> Hi Pete,
>> 
>> how would you instantiate a client proxy, if not via a
>> constructor? You need one call for the proxy and one call
>> for the 'contextual instance'.
>> Or am I missing some available java-magic?
>> 
>> Regards,
>> Arne
>> 
>> -----Ursprüngliche Nachricht-----
>> Von: cdi-dev-bounces at lists.jboss.org
>> [mailto:cdi-dev-bounces at lists.jboss.org]
>> Im Auftrag von Pete Muir
>> Gesendet: Montag, 9. Mai 2011 17:20
>> An: Mark Struberg
>> Cc: cdi-dev at lists.jboss.org
>> Betreff: Re: [cdi-dev] Proxy implementation leaks
>> 
>> Thanks Mark, I knew there was a reason for the lazy init.
>> 
>> The two-ctor call is not necessary though.
>> 
>> On 9 May 2011, at 16:15, Mark Struberg wrote:
>> 
>>> actually this behaviour is pretty clear in EE. It's
>> the same thing as we have with EJBs since almost ever.
>> That's why @PostConstruct exists.
>>> 
>>> Whenever object proxies or hidden/transparent
>> serialisation happens, then we need to create the
>> object/proxy on the other side/new invocation. And everytime
>> this happens, the constructer will obviously get called.
>>> 
>>> So this is not a bug and surely not a leak!
>>> 
>>> This was on our list when I did a talk about CDI
>> pitfalls at the JSFdays last year together with Dan.
>>> 
>>> Maybe we should doument this better, but it's nothing
>> for the spec, but the user documentation imo.
>>> 
>>> Also the lazy init is imo a well specified and welcome
>> behaviour. Look at the discussions way back about how to
>> prevent cyclic injection problems.
>>> 
>>> LieGrue,
>>> strub
>>> 
>>> --- On Mon, 5/9/11, Christian Bauer <christian.bauer at gmail.com>
>> wrote:
>>> 
>>>> From: Christian Bauer <christian.bauer at gmail.com>
>>>> Subject: [cdi-dev] Proxy implementation leaks
>>>> To: cdi-dev at lists.jboss.org
>>>> Date: Monday, May 9, 2011, 2:46 PM
>>>> Started working with Weld 1.1.1 and
>>>> found two issues that probably should be addressed
>> (maybe just 
>>>> documented). They both look to me like leaking
>> implementation details 
>>>> because proxies are used for components which are
>> not @Singleton or 
>>>> @Dependent.
>>>> 
>>>> @ApplicationScoped
>>>> public class Bug {
>>>> 
>>>>     public Bug() {
>>>>     
>>>>     System.out.println("##########
>>>> CONSTRUCT");
>>>>     }
>>>> 
>>>>     public void foo() {
>>>>        
>> System.out.println("#####
>>>> FOO");
>>>>     }
>>>> 
>>>>     public static void main(String[]
>> args) {
>>>>         Weld weld = new
>> Weld();
>>>>         WeldContainer
>> weldContainer
>>>> = weld.initialize();
>>>> 
>>>>         Bug bug =
>>>> weldContainer.instance().select(Bug.class).get();
>> // Creates new 
>>>> instance of Bug
>>>>         bug.foo(); // Creates
>> new
>>>> instance of Bug!!!
>>>>         bug.foo(); // Uses
>> existing
>>>> instance
>>>> 
>>>>         weld.shutdown();
>>>>     }
>>>> }
>>>> 
>>>> The proxy of Bug will call its superclass
>> constructor several times 
>>>> during the lifecycle of the Bug component. I don't
>> know if that is 
>>>> really necessary, but if it is, you can now no
>> longer use 
>>>> constructors to initialize your component. This is
>> an issue because
>>>> 
>>>> - it's not documented that constructors of
>> @ApplciationScoped (etc., 
>>>> proxied) components behave differently than
>> @Singleton/@Dependent 
>>>> constructors
>>>> 
>>>> - even if it's documented, it's questionable if
>> that really should be 
>>>> the case.
>>>> 
>>>> Taking away constructors as the primary means of
>> initializing a 
>>>> component - e.g. obtaining resources such as
>> database connections, 
>>>> reading config files, etc. - is a major change in
>> the Java 
>>>> programming model. Users have to be strongly
>> advised to use 
>>>> @PostConstruct then.
>>>> 
>>>> The other issue I immediately found is also
>> related to behavior of 
>>>> proxies and how transitive initializing/injection
>> is implemented (not 
>>>> sure if this is actually specified somewhere):
>>>> 
>>>> @ApplicationScoped
>>>> public class Foo {
>>>> 
>>>>     @Inject
>>>>     Bar bar;
>>>> 
>>>> }
>>>> 
>>>> @ApplicationScoped
>>>> public class Bar {
>>>> 
>>>>      @Inject
>>>>      Baz baz;
>>>> 
>>>>      @PostConstruct
>>>>      void init() { ... }
>>>> 
>>>> }
>>>> 
>>>> When I obtain a reference to Foo, I get a proxy of
>> Foo with a 
>>>> reference to a proxy of Bar. The init() method of
>> Bar is never 
>>>> called. The Baz component is never activated.
>>>> 
>>>> This means I can't transitively initialize an
>> application-scoped 
>>>> graph of components. I was trying to use CDI for
>> wiring in a Swing 
>>>> application and I imagine this would be a common
>> usecase. It should 
>>>> either be documented that there is a difference
>> between 
>>>> @Singleton/@Dependent and proxy-implemented
>> scopes, or unification 
>>>> should be considered.
>>>> 
>>>> 
>>>> _______________________________________________
>>>> cdi-dev mailing list
>>>> cdi-dev at lists.jboss.org
>>>> https://lists.jboss.org/mailman/listinfo/cdi-dev
>>>> 
>> 
>> 
>> _______________________________________________
>> cdi-dev mailing list
>> cdi-dev at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/cdi-dev
>> 




More information about the cdi-dev mailing list