[cdi-dev] Proxy implementation leaks

Mark Struberg struberg at yahoo.de
Mon May 9 11:34:23 EDT 2011


imo once for *every* instance you create.

And each proxy == instance imo.

Marius, Stuuu, think we need you guys to clarify this.

txs and LieGrue,
strub

--- On Mon, 5/9/11, Pete Muir <pmuir at redhat.com> wrote:

> From: Pete Muir <pmuir at redhat.com>
> Subject: Re: AW: [cdi-dev] Proxy implementation leaks
> To: "Mark Struberg" <struberg at yahoo.de>
> Cc: "Arne Limburg" <arne.limburg at openknowledge.de>, "cdi-dev at lists.jboss.org" <cdi-dev at lists.jboss.org>
> Date: Monday, May 9, 2011, 3:32 PM
> 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