You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@openjpa.apache.org by Mark Struberg <st...@yahoo.de.INVALID> on 2020/07/17 07:34:21 UTC

A few runtime enhancement/bytecode questions

hi folks!

I'm right now cleaning up old code in our enhancer. Like removing java5 hacks, etc
This is also triggered by our recent discussion about _transform and other pieces.
Slowly getting my head into the right space for it. This is way more complex than I remembered ;)

So here is my next puzzle:

I've created a new example with 2 classes: Person and Employee extends Person
Plus a persistence.xml with enlisting those 2 classes (makes a difference!) and essentially
<property name="openjpa.DynamicEnhancementAgent" value="true"/>
<property name="openjpa.RuntimeUnenhancedClasses" value="supported"/>
The reason I switched on RuntimeUnenhancedClasses is that this check is performed when the BrokerFactory gets created.
And if the classes are not build-time enhanced, then it fails in 
org.apache.openjpa.enhance.ManagedClassSubclasser#prepareUnenhancedClasses
if (conf.getRuntimeUnenhancedClassesConstant() != RuntimeUnenhancedClassesModes.SUPPORTED) { ..
And if you switch to supported, then it will create a new subclass and replaces field access to the getters/setters. Sadly java.lang.instrument.Instrumentation#retransform cannot be used to add new fields or methods. Otherwise we could do a direct full replacement of this class.

Fun thing is that later on in 
org.apache.openjpa.persistence.PersistenceProviderImpl#createEntityManagerFactory(java.lang.String, java.lang.String, java.util.Map)
we call loadAgent(factory);
But what is it supposed to do? Which cases does it serve?
If the classes did not have been already enhanced at build time nor via javaagent they will now be subclassed by ManagedClassSubclasser.
And if we do not set RuntimeUnenhancedClasses=supported then we will never make it so far but blow up way earlier.

Also: it is nice to have that agent attached. But why? All the entity classe already have been loaded already during BrokerFactory startup. There is no more entity class left over which needs enhancement, isn't?

This is the log I get which reflects what I mean. Happy to share the code in a playground branch.

1261  test-classtransform  INFO   [main] openjpa.Enhance - Creating subclass and redefining methods for "[class org.apache.openjpa.examples.dynenhance.Employee, class org.apache.openjpa.examples.dynenhance.Person]". This means that your application will be less efficient than it would if you ran the OpenJPA enhancer.
1412  test-classtransform  INFO   [main] openjpa.Runtime - OpenJPA dynamically loaded the class enhancer. Any classes that were not enhanced at build time will be enhanced when they are loaded by the JVM.


LieGrue,
strub


Re: A few runtime enhancement/bytecode questions

Posted by Romain Manni-Bucau <rm...@gmail.com>.
PS: 6. when you synchronize mapping, classes are loaded earlier than when
you don't

Romain Manni-Bucau
@rmannibucau <https://twitter.com/rmannibucau> |  Blog
<https://rmannibucau.metawerx.net/> | Old Blog
<http://rmannibucau.wordpress.com> | Github <https://github.com/rmannibucau> |
LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
<https://www.packtpub.com/application-development/java-ee-8-high-performance>


Le ven. 17 juil. 2020 à 10:11, Romain Manni-Bucau <rm...@gmail.com> a
écrit :

> Hi Mark,
>
> If it helps:
>
> 1. org.apache.openjpa.kernel.AbstractBrokerFactory#postCreationCallback
> only triggers the prepareUnenhancedClasses if preload=true (never the case
> right? ;))
> 2. Normally classes are loaded in
> there org.apache.openjpa.kernel.AbstractBrokerFactory#initializeBroker
> *when creating an em, not an emf* so better to have loaded ran the
> enhancement early (loadAgent)
> 3. Not sure it is done but it can happen 2 has a custom MDR not returning
> right the classes - seems code is ok with that. I don't know if it is a
> case we want to handle, I don't think it is needed.
> 4. There is another case you didn't list where the EMF can be there but no
> EM and enhancement should happen ASAP: deserialization ;)
> 5. Finally there is a subtle difference between SE and EE case where one
> will trigger the agent and the other will just add the transformer in the
> classloader through PersistenUnitInfo (and container should handle this
> additional properly), I don't know if our agent should be compatible with
> it for apploader (jvm one).
>
> Romain Manni-Bucau
> @rmannibucau <https://twitter.com/rmannibucau> |  Blog
> <https://rmannibucau.metawerx.net/> | Old Blog
> <http://rmannibucau.wordpress.com> | Github
> <https://github.com/rmannibucau> | LinkedIn
> <https://www.linkedin.com/in/rmannibucau> | Book
> <https://www.packtpub.com/application-development/java-ee-8-high-performance>
>
>
> Le ven. 17 juil. 2020 à 09:35, Mark Struberg <st...@yahoo.de.invalid>
> a écrit :
>
>> hi folks!
>>
>> I'm right now cleaning up old code in our enhancer. Like removing java5
>> hacks, etc
>> This is also triggered by our recent discussion about _transform and
>> other pieces.
>> Slowly getting my head into the right space for it. This is way more
>> complex than I remembered ;)
>>
>> So here is my next puzzle:
>>
>> I've created a new example with 2 classes: Person and Employee extends
>> Person
>> Plus a persistence.xml with enlisting those 2 classes (makes a
>> difference!) and essentially
>> <property name="openjpa.DynamicEnhancementAgent" value="true"/>
>> <property name="openjpa.RuntimeUnenhancedClasses" value="supported"/>
>> The reason I switched on RuntimeUnenhancedClasses is that this check is
>> performed when the BrokerFactory gets created.
>> And if the classes are not build-time enhanced, then it fails in
>> org.apache.openjpa.enhance.ManagedClassSubclasser#prepareUnenhancedClasses
>> if (conf.getRuntimeUnenhancedClassesConstant() !=
>> RuntimeUnenhancedClassesModes.SUPPORTED) { ..
>> And if you switch to supported, then it will create a new subclass and
>> replaces field access to the getters/setters. Sadly
>> java.lang.instrument.Instrumentation#retransform cannot be used to add new
>> fields or methods. Otherwise we could do a direct full replacement of this
>> class.
>>
>> Fun thing is that later on in
>> org.apache.openjpa.persistence.PersistenceProviderImpl#createEntityManagerFactory(java.lang.String,
>> java.lang.String, java.util.Map)
>> we call loadAgent(factory);
>> But what is it supposed to do? Which cases does it serve?
>> If the classes did not have been already enhanced at build time nor via
>> javaagent they will now be subclassed by ManagedClassSubclasser.
>> And if we do not set RuntimeUnenhancedClasses=supported then we will
>> never make it so far but blow up way earlier.
>>
>> Also: it is nice to have that agent attached. But why? All the entity
>> classe already have been loaded already during BrokerFactory startup. There
>> is no more entity class left over which needs enhancement, isn't?
>>
>> This is the log I get which reflects what I mean. Happy to share the code
>> in a playground branch.
>>
>> 1261  test-classtransform  INFO   [main] openjpa.Enhance - Creating
>> subclass and redefining methods for "[class
>> org.apache.openjpa.examples.dynenhance.Employee, class
>> org.apache.openjpa.examples.dynenhance.Person]". This means that your
>> application will be less efficient than it would if you ran the OpenJPA
>> enhancer.
>> 1412  test-classtransform  INFO   [main] openjpa.Runtime - OpenJPA
>> dynamically loaded the class enhancer. Any classes that were not enhanced
>> at build time will be enhanced when they are loaded by the JVM.
>>
>>
>> LieGrue,
>> strub
>>
>>

Re: A few runtime enhancement/bytecode questions

Posted by Romain Manni-Bucau <rm...@gmail.com>.
Le dim. 19 juil. 2020 à 23:25, Mark Struberg <st...@yahoo.de.invalid> a
écrit :

>
>
> > Am 19.07.2020 um 06:42 schrieb Romain Manni-Bucau <rmannibucau@gmail.com
> >:
> >
> > Le dim. 19 juil. 2020 à 00:47, Mark Struberg <st...@yahoo.de.invalid>
> a
> > écrit :
> >
> >> Yes, it seems that the recursive call is just from using an openjpa
> class
> >> when the first javaagent transformer starts it's work.
> >> That means before any openjpa code is actually used. This _could_ be
> >> prevented if the premain code in the agent would touch all the necessary
> >> classes. But of course this is error prone as well.
> >>
> >
> > Not in EE case where enhancer classes will be loaded by the transformer
> and
> > never the agent.
> > Also can not be with a custom openjpa spi loading classes (if we exclude
> > this case, im for it, we should write it in our doc somewhere probably
> just
> > to not forget again).
>
> That's just a question where we place it.


> >
> >
> >> For any entity etc it will not be called recursively. The
> >> java.lang.instrument.ClassFileTransformer#transform method just returns
> a
> >> byte[] with the new bytecode. But it does not interpret that bytecode
> >> during transformation. Thus no recursive call.
> >>
> >
> > Well it can with asm but using tmploader so until you do like me in
> > embedded case (or optim in tomee), apploader=tmploader + cds, to save a
> lot
> > of time, then it works.
> >
> > We could use a ThreadLocal<AtomicBoolean> and even set it to null after
> the
> >> first run. Because once openjpa is initted we should not see any
> recursive
> >> invocations anymore. Something like that.
> >>
> >
> > Also means we dont need that and can just exclude openjpa stack as i
> > proposed whicj makes the method "pure" which is saner and like as fast in
> > general case (in terms of complexity).
> > So sounds saner.
>
> This is the same problem like with the pre-init: which classes exactly?
>

The one of the PR? ;)
Actually a bit less is needed but the pr is done in a way which does not
hurt perfs and avoids to leak a state between calls which is very nasty (as
proven by this thread) and uncontrollable - strictly speaking names test
should happen before the threadlocal, then next test etc....blacklisting
avoids it cleanly.
We can refine thz classes graph if needed but packages are more than enough.


> In your case we have to exclude that classes from transformation.
> In the other case we load those classes before the PCClassFileTransformer
> gets installed.
> Both cases have the downside that you need to exactly know which classes
> will get loaded.
>
> After going through all the pros and cons I am in favour for the
> ThreadLocal.
> This could really already also hit any Tomcat installation which enables
> parallel war loading and has openjpa in the shared classloader, right?
>

Even a plain standalone app.


> LieGrue,
> strub
>
>
> >
> >
> >> LieGrue,
> >> strub
> >>
> >>> Am 18.07.2020 um 18:18 schrieb Romain Manni-Bucau <
> rmannibucau@gmail.com
> >>> :
> >>>
> >>> Oh just got it, you need to extend openjpa (MDR for ex) otherwise it
> does
> >>> only happen if openjpa is not loaded during the enhancement, which
> means
> >>> the javaagent is there, the entity is loaded but the EMF not yet there,
> >> so
> >>> 2 cases (even if one is unlikely but can happen due to our spi).
> >>>
> >>> Romain Manni-Bucau
> >>> @rmannibucau <https://twitter.com/rmannibucau> |  Blog
> >>> <https://rmannibucau.metawerx.net/> | Old Blog
> >>> <http://rmannibucau.wordpress.com> | Github <
> >> https://github.com/rmannibucau> |
> >>> LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
> >>> <
> >>
> https://www.packtpub.com/application-development/java-ee-8-high-performance
> >>>
> >>>
> >>>
> >>> Le sam. 18 juil. 2020 à 18:07, Mark Struberg <struberg@yahoo.de.invalid
> >
> >> a
> >>> écrit :
> >>>
> >>>> no, didn't work.
> >>>>
> >>>> LieGrue,
> >>>> strub
> >>>>
> >>>>
> >>>>> Am 18.07.2020 um 18:00 schrieb Romain Manni-Bucau <
> >> rmannibucau@gmail.com
> >>>>> :
> >>>>>
> >>>>> Not sure I got the question but I suspect the case can be reproduced
> >>>> with a
> >>>>> plain new MyEntity() before your Persistence.createEMF.
> >>>>>
> >>>>> Romain Manni-Bucau
> >>>>> @rmannibucau <https://twitter.com/rmannibucau> |  Blog
> >>>>> <https://rmannibucau.metawerx.net/> | Old Blog
> >>>>> <http://rmannibucau.wordpress.com> | Github <
> >>>> https://github.com/rmannibucau> |
> >>>>> LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
> >>>>> <
> >>>>
> >>
> https://www.packtpub.com/application-development/java-ee-8-high-performance
> >>>>>
> >>>>>
> >>>>>
> >>>>> Le sam. 18 juil. 2020 à 17:57, Mark Struberg
> <struberg@yahoo.de.invalid
> >>>
> >>>> a
> >>>>> écrit :
> >>>>>
> >>>>>> Found it yesterday when reviewing my sample with Romain:
> >>>>>>
> >>>>>> I apparently did copy the following property over from another
> >> example:
> >>>>>> <property name="openjpa.InitializeEagerly" value="true"/>
> >>>>>> And this did lead to already trigger the class transformation while
> >>>>>> createEntityManagerFactory.
> >>>>>>
> >>>>>> I did create a few samples, but did not manage to trigger any
> >> subsequent
> >>>>>> classloading at all. So no wonder in which case this could hit us
> yet.
> >>>>>> Before we introduce another expensive mechanism I would love to
> >>>> understand
> >>>>>> when the situation occurs at all.
> >>>>>>
> >>>>>> LieGrue,
> >>>>>> strub
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>> Am 17.07.2020 um 12:03 schrieb Romain Manni-Bucau <
> >>>> rmannibucau@gmail.com
> >>>>>>> :
> >>>>>>>
> >>>>>>> Le ven. 17 juil. 2020 à 11:27, Mark Struberg
> >> <struberg@yahoo.de.invalid
> >>>>>> <ma...@yahoo.de.invalid>> a
> >>>>>>> écrit :
> >>>>>>>
> >>>>>>>> answers inside.
> >>>>>>>>
> >>>>>>>> LieGrue,
> >>>>>>>> strub
> >>>>>>>>
> >>>>>>>>> Am 17.07.2020 um 11:14 schrieb Romain Manni-Bucau <
> >>>>>> rmannibucau@gmail.com
> >>>>>>>>> :
> >>>>>>>>>
> >>>>>>>>> Le ven. 17 juil. 2020 à 10:45, Mark Struberg
> >>>> <struberg@yahoo.de.invalid
> >>>>>>>
> >>>>>>>> a
> >>>>>>>>> écrit :
> >>>>>>>>>
> >>>>>>>>>> Both prepareUnenhancedClasses and loadAgent already run in
> >>>>>>>>>> createEntityManagerFactory.
> >>>>>>>>>>
> >>>>>>>>>
> >>>>>>>>> Not in general, depends the conf and by default i run in none of
> >> both
> >>>>>>>> with
> >>>>>>>>> a standard config for ex for EE.
> >>>>>>>>
> >>>>>>>> Let me rephrase this: both those methods will get called in
> >>>>>>>> createEntityManagerFactory already. If they actually perform some
> >>>>>> bytecode
> >>>>>>>> enhancement is up to configuration and whether the classes have
> been
> >>>>>>>> enhanced otherwise before ;)
> >>>>>>>>
> >>>>>>>>
> >>>>>>>>>
> >>>>>>>>>
> >>>>>>>>>> crateEntityManager does not trigger enhancement afaict.
> >>>>>>>>>>
> >>>>>>>>>
> >>>>>>>>> createEMF does not since the creation of openjpa is lazy so the
> >> first
> >>>>>>>>> createEM does (in general case one again).
> >>>>>>>>
> >>>>>>>> Nope, it really gets called already by createEntityManagerFactory.
> >> You
> >>>>>> can
> >>>>>>>> debug into this if you want.
> >>>>>>>>
> >>>>>>>
> >>>>>>> Did and I can guarantee you it is lazy if your conf does not
> enforce
> >> it
> >>>>>>> somehow.
> >>>>>>>
> >>>>>>>
> >>>>>>>>
> >>>>>>>> LieGrue,
> >>>>>>>> strub
> >>>>>>>>
> >>>>>>>>
> >>>>>>>>>
> >>>>>>>>>>
> >>>>>>>>>> LieGrue,
> >>>>>>>>>> strub
> >>>>>>>>>>
> >>>>>>>>>>> Am 17.07.2020 um 10:11 schrieb Romain Manni-Bucau <
> >>>>>>>> rmannibucau@gmail.com
> >>>>>>>>>>> :
> >>>>>>>>>>>
> >>>>>>>>>>> Hi Mark,
> >>>>>>>>>>>
> >>>>>>>>>>> If it helps:
> >>>>>>>>>>>
> >>>>>>>>>>> 1.
> >>>>>> org.apache.openjpa.kernel.AbstractBrokerFactory#postCreationCallback
> >>>>>>>>>>> only triggers the prepareUnenhancedClasses if preload=true
> (never
> >>>> the
> >>>>>>>>>> case
> >>>>>>>>>>> right? ;))
> >>>>>>>>>>> 2. Normally classes are loaded in
> >>>>>>>>>>> there
> >>>>>> org.apache.openjpa.kernel.AbstractBrokerFactory#initializeBroker
> >>>>>>>>>>> *when creating an em, not an emf* so better to have loaded ran
> >> the
> >>>>>>>>>>> enhancement early (loadAgent)
> >>>>>>>>>>> 3. Not sure it is done but it can happen 2 has a custom MDR not
> >>>>>>>> returning
> >>>>>>>>>>> right the classes - seems code is ok with that. I don't know if
> >> it
> >>>>>> is a
> >>>>>>>>>>> case we want to handle, I don't think it is needed.
> >>>>>>>>>>> 4. There is another case you didn't list where the EMF can be
> >> there
> >>>>>> but
> >>>>>>>>>> no
> >>>>>>>>>>> EM and enhancement should happen ASAP: deserialization ;)
> >>>>>>>>>>> 5. Finally there is a subtle difference between SE and EE case
> >>>> where
> >>>>>>>> one
> >>>>>>>>>>> will trigger the agent and the other will just add the
> >> transformer
> >>>> in
> >>>>>>>> the
> >>>>>>>>>>> classloader through PersistenUnitInfo (and container should
> >> handle
> >>>>>> this
> >>>>>>>>>>> additional properly), I don't know if our agent should be
> >>>> compatible
> >>>>>>>> with
> >>>>>>>>>>> it for apploader (jvm one).
> >>>>>>>>>>>
> >>>>>>>>>>> Romain Manni-Bucau
> >>>>>>>>>>> @rmannibucau <https://twitter.com/rmannibucau> |  Blog
> >>>>>>>>>>> <https://rmannibucau.metawerx.net/> | Old Blog
> >>>>>>>>>>> <http://rmannibucau.wordpress.com> | Github <
> >>>>>>>>>> https://github.com/rmannibucau> |
> >>>>>>>>>>> LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
> >>>>>>>>>>> <
> >>>>>>>>>>
> >>>>>>>>
> >>>>>>
> >>>>
> >>
> https://www.packtpub.com/application-development/java-ee-8-high-performance
> >>>>>>>>>>>
> >>>>>>>>>>>
> >>>>>>>>>>>
> >>>>>>>>>>> Le ven. 17 juil. 2020 à 09:35, Mark Struberg
> >>>>>> <struberg@yahoo.de.invalid
> >>>>>>>>>
> >>>>>>>>>> a
> >>>>>>>>>>> écrit :
> >>>>>>>>>>>
> >>>>>>>>>>>> hi folks!
> >>>>>>>>>>>>
> >>>>>>>>>>>> I'm right now cleaning up old code in our enhancer. Like
> >> removing
> >>>>>>>> java5
> >>>>>>>>>>>> hacks, etc
> >>>>>>>>>>>> This is also triggered by our recent discussion about
> _transform
> >>>> and
> >>>>>>>>>> other
> >>>>>>>>>>>> pieces.
> >>>>>>>>>>>> Slowly getting my head into the right space for it. This is
> way
> >>>> more
> >>>>>>>>>>>> complex than I remembered ;)
> >>>>>>>>>>>>
> >>>>>>>>>>>> So here is my next puzzle:
> >>>>>>>>>>>>
> >>>>>>>>>>>> I've created a new example with 2 classes: Person and Employee
> >>>>>> extends
> >>>>>>>>>>>> Person
> >>>>>>>>>>>> Plus a persistence.xml with enlisting those 2 classes (makes a
> >>>>>>>>>>>> difference!) and essentially
> >>>>>>>>>>>> <property name="openjpa.DynamicEnhancementAgent"
> value="true"/>
> >>>>>>>>>>>> <property name="openjpa.RuntimeUnenhancedClasses"
> >>>>>> value="supported"/>
> >>>>>>>>>>>> The reason I switched on RuntimeUnenhancedClasses is that this
> >>>> check
> >>>>>>>> is
> >>>>>>>>>>>> performed when the BrokerFactory gets created.
> >>>>>>>>>>>> And if the classes are not build-time enhanced, then it fails
> in
> >>>>>>>>>>>>
> >>>>>>>>>>
> >>>>>>>>
> >>>>>>
> >>>>
> >>
> org.apache.openjpa.enhance.ManagedClassSubclasser#prepareUnenhancedClasses
> >>>>>>>>>>>> if (conf.getRuntimeUnenhancedClassesConstant() !=
> >>>>>>>>>>>> RuntimeUnenhancedClassesModes.SUPPORTED) { ..
> >>>>>>>>>>>> And if you switch to supported, then it will create a new
> >> subclass
> >>>>>> and
> >>>>>>>>>>>> replaces field access to the getters/setters. Sadly
> >>>>>>>>>>>> java.lang.instrument.Instrumentation#retransform cannot be
> used
> >> to
> >>>>>> add
> >>>>>>>>>> new
> >>>>>>>>>>>> fields or methods. Otherwise we could do a direct full
> >> replacement
> >>>>>> of
> >>>>>>>>>> this
> >>>>>>>>>>>> class.
> >>>>>>>>>>>>
> >>>>>>>>>>>> Fun thing is that later on in
> >>>>>>>>>>>>
> >>>>>>>>>>
> >>>>>>>>
> >>>>>>
> >>>>
> >>
> org.apache.openjpa.persistence.PersistenceProviderImpl#createEntityManagerFactory(java.lang.String,
> >>>>>>>>>>>> java.lang.String, java.util.Map)
> >>>>>>>>>>>> we call loadAgent(factory);
> >>>>>>>>>>>> But what is it supposed to do? Which cases does it serve?
> >>>>>>>>>>>> If the classes did not have been already enhanced at build
> time
> >>>> nor
> >>>>>>>> via
> >>>>>>>>>>>> javaagent they will now be subclassed by
> ManagedClassSubclasser.
> >>>>>>>>>>>> And if we do not set RuntimeUnenhancedClasses=supported then
> we
> >>>> will
> >>>>>>>>>> never
> >>>>>>>>>>>> make it so far but blow up way earlier.
> >>>>>>>>>>>>
> >>>>>>>>>>>> Also: it is nice to have that agent attached. But why? All the
> >>>>>> entity
> >>>>>>>>>>>> classe already have been loaded already during BrokerFactory
> >>>>>> startup.
> >>>>>>>>>> There
> >>>>>>>>>>>> is no more entity class left over which needs enhancement,
> >> isn't?
> >>>>>>>>>>>>
> >>>>>>>>>>>> This is the log I get which reflects what I mean. Happy to
> share
> >>>> the
> >>>>>>>>>> code
> >>>>>>>>>>>> in a playground branch.
> >>>>>>>>>>>>
> >>>>>>>>>>>> 1261  test-classtransform  INFO   [main] openjpa.Enhance -
> >>>> Creating
> >>>>>>>>>>>> subclass and redefining methods for "[class
> >>>>>>>>>>>> org.apache.openjpa.examples.dynenhance.Employee, class
> >>>>>>>>>>>> org.apache.openjpa.examples.dynenhance.Person]". This means
> that
> >>>>>> your
> >>>>>>>>>>>> application will be less efficient than it would if you ran
> the
> >>>>>>>> OpenJPA
> >>>>>>>>>>>> enhancer.
> >>>>>>>>>>>> 1412  test-classtransform  INFO   [main] openjpa.Runtime -
> >> OpenJPA
> >>>>>>>>>>>> dynamically loaded the class enhancer. Any classes that were
> not
> >>>>>>>>>> enhanced
> >>>>>>>>>>>> at build time will be enhanced when they are loaded by the
> JVM.
> >>>>>>>>>>>>
> >>>>>>>>>>>>
> >>>>>>>>>>>> LieGrue,
> >>>>>>>>>>>> strub
> >>>>>>
> >>>>>>
> >>>>
> >>>>
> >>
> >>
>
>

Re: A few runtime enhancement/bytecode questions

Posted by Mark Struberg <st...@yahoo.de.INVALID>.

> Am 19.07.2020 um 06:42 schrieb Romain Manni-Bucau <rm...@gmail.com>:
> 
> Le dim. 19 juil. 2020 à 00:47, Mark Struberg <st...@yahoo.de.invalid> a
> écrit :
> 
>> Yes, it seems that the recursive call is just from using an openjpa class
>> when the first javaagent transformer starts it's work.
>> That means before any openjpa code is actually used. This _could_ be
>> prevented if the premain code in the agent would touch all the necessary
>> classes. But of course this is error prone as well.
>> 
> 
> Not in EE case where enhancer classes will be loaded by the transformer and
> never the agent.
> Also can not be with a custom openjpa spi loading classes (if we exclude
> this case, im for it, we should write it in our doc somewhere probably just
> to not forget again).

That's just a question where we place it.

> 
> 
>> For any entity etc it will not be called recursively. The
>> java.lang.instrument.ClassFileTransformer#transform method just returns a
>> byte[] with the new bytecode. But it does not interpret that bytecode
>> during transformation. Thus no recursive call.
>> 
> 
> Well it can with asm but using tmploader so until you do like me in
> embedded case (or optim in tomee), apploader=tmploader + cds, to save a lot
> of time, then it works.
> 
> We could use a ThreadLocal<AtomicBoolean> and even set it to null after the
>> first run. Because once openjpa is initted we should not see any recursive
>> invocations anymore. Something like that.
>> 
> 
> Also means we dont need that and can just exclude openjpa stack as i
> proposed whicj makes the method "pure" which is saner and like as fast in
> general case (in terms of complexity).
> So sounds saner.

This is the same problem like with the pre-init: which classes exactly?

In your case we have to exclude that classes from transformation.
In the other case we load those classes before the PCClassFileTransformer gets installed.
Both cases have the downside that you need to exactly know which classes will get loaded.

After going through all the pros and cons I am in favour for the ThreadLocal.
This could really already also hit any Tomcat installation which enables parallel war loading and has openjpa in the shared classloader, right?

LieGrue,
strub


> 
> 
>> LieGrue,
>> strub
>> 
>>> Am 18.07.2020 um 18:18 schrieb Romain Manni-Bucau <rmannibucau@gmail.com
>>> :
>>> 
>>> Oh just got it, you need to extend openjpa (MDR for ex) otherwise it does
>>> only happen if openjpa is not loaded during the enhancement, which means
>>> the javaagent is there, the entity is loaded but the EMF not yet there,
>> so
>>> 2 cases (even if one is unlikely but can happen due to our spi).
>>> 
>>> Romain Manni-Bucau
>>> @rmannibucau <https://twitter.com/rmannibucau> |  Blog
>>> <https://rmannibucau.metawerx.net/> | Old Blog
>>> <http://rmannibucau.wordpress.com> | Github <
>> https://github.com/rmannibucau> |
>>> LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
>>> <
>> https://www.packtpub.com/application-development/java-ee-8-high-performance
>>> 
>>> 
>>> 
>>> Le sam. 18 juil. 2020 à 18:07, Mark Struberg <st...@yahoo.de.invalid>
>> a
>>> écrit :
>>> 
>>>> no, didn't work.
>>>> 
>>>> LieGrue,
>>>> strub
>>>> 
>>>> 
>>>>> Am 18.07.2020 um 18:00 schrieb Romain Manni-Bucau <
>> rmannibucau@gmail.com
>>>>> :
>>>>> 
>>>>> Not sure I got the question but I suspect the case can be reproduced
>>>> with a
>>>>> plain new MyEntity() before your Persistence.createEMF.
>>>>> 
>>>>> Romain Manni-Bucau
>>>>> @rmannibucau <https://twitter.com/rmannibucau> |  Blog
>>>>> <https://rmannibucau.metawerx.net/> | Old Blog
>>>>> <http://rmannibucau.wordpress.com> | Github <
>>>> https://github.com/rmannibucau> |
>>>>> LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
>>>>> <
>>>> 
>> https://www.packtpub.com/application-development/java-ee-8-high-performance
>>>>> 
>>>>> 
>>>>> 
>>>>> Le sam. 18 juil. 2020 à 17:57, Mark Struberg <struberg@yahoo.de.invalid
>>> 
>>>> a
>>>>> écrit :
>>>>> 
>>>>>> Found it yesterday when reviewing my sample with Romain:
>>>>>> 
>>>>>> I apparently did copy the following property over from another
>> example:
>>>>>> <property name="openjpa.InitializeEagerly" value="true"/>
>>>>>> And this did lead to already trigger the class transformation while
>>>>>> createEntityManagerFactory.
>>>>>> 
>>>>>> I did create a few samples, but did not manage to trigger any
>> subsequent
>>>>>> classloading at all. So no wonder in which case this could hit us yet.
>>>>>> Before we introduce another expensive mechanism I would love to
>>>> understand
>>>>>> when the situation occurs at all.
>>>>>> 
>>>>>> LieGrue,
>>>>>> strub
>>>>>> 
>>>>>> 
>>>>>> 
>>>>>> 
>>>>>> 
>>>>>>> Am 17.07.2020 um 12:03 schrieb Romain Manni-Bucau <
>>>> rmannibucau@gmail.com
>>>>>>> :
>>>>>>> 
>>>>>>> Le ven. 17 juil. 2020 à 11:27, Mark Struberg
>> <struberg@yahoo.de.invalid
>>>>>> <ma...@yahoo.de.invalid>> a
>>>>>>> écrit :
>>>>>>> 
>>>>>>>> answers inside.
>>>>>>>> 
>>>>>>>> LieGrue,
>>>>>>>> strub
>>>>>>>> 
>>>>>>>>> Am 17.07.2020 um 11:14 schrieb Romain Manni-Bucau <
>>>>>> rmannibucau@gmail.com
>>>>>>>>> :
>>>>>>>>> 
>>>>>>>>> Le ven. 17 juil. 2020 à 10:45, Mark Struberg
>>>> <struberg@yahoo.de.invalid
>>>>>>> 
>>>>>>>> a
>>>>>>>>> écrit :
>>>>>>>>> 
>>>>>>>>>> Both prepareUnenhancedClasses and loadAgent already run in
>>>>>>>>>> createEntityManagerFactory.
>>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> Not in general, depends the conf and by default i run in none of
>> both
>>>>>>>> with
>>>>>>>>> a standard config for ex for EE.
>>>>>>>> 
>>>>>>>> Let me rephrase this: both those methods will get called in
>>>>>>>> createEntityManagerFactory already. If they actually perform some
>>>>>> bytecode
>>>>>>>> enhancement is up to configuration and whether the classes have been
>>>>>>>> enhanced otherwise before ;)
>>>>>>>> 
>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>>> crateEntityManager does not trigger enhancement afaict.
>>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> createEMF does not since the creation of openjpa is lazy so the
>> first
>>>>>>>>> createEM does (in general case one again).
>>>>>>>> 
>>>>>>>> Nope, it really gets called already by createEntityManagerFactory.
>> You
>>>>>> can
>>>>>>>> debug into this if you want.
>>>>>>>> 
>>>>>>> 
>>>>>>> Did and I can guarantee you it is lazy if your conf does not enforce
>> it
>>>>>>> somehow.
>>>>>>> 
>>>>>>> 
>>>>>>>> 
>>>>>>>> LieGrue,
>>>>>>>> strub
>>>>>>>> 
>>>>>>>> 
>>>>>>>>> 
>>>>>>>>>> 
>>>>>>>>>> LieGrue,
>>>>>>>>>> strub
>>>>>>>>>> 
>>>>>>>>>>> Am 17.07.2020 um 10:11 schrieb Romain Manni-Bucau <
>>>>>>>> rmannibucau@gmail.com
>>>>>>>>>>> :
>>>>>>>>>>> 
>>>>>>>>>>> Hi Mark,
>>>>>>>>>>> 
>>>>>>>>>>> If it helps:
>>>>>>>>>>> 
>>>>>>>>>>> 1.
>>>>>> org.apache.openjpa.kernel.AbstractBrokerFactory#postCreationCallback
>>>>>>>>>>> only triggers the prepareUnenhancedClasses if preload=true (never
>>>> the
>>>>>>>>>> case
>>>>>>>>>>> right? ;))
>>>>>>>>>>> 2. Normally classes are loaded in
>>>>>>>>>>> there
>>>>>> org.apache.openjpa.kernel.AbstractBrokerFactory#initializeBroker
>>>>>>>>>>> *when creating an em, not an emf* so better to have loaded ran
>> the
>>>>>>>>>>> enhancement early (loadAgent)
>>>>>>>>>>> 3. Not sure it is done but it can happen 2 has a custom MDR not
>>>>>>>> returning
>>>>>>>>>>> right the classes - seems code is ok with that. I don't know if
>> it
>>>>>> is a
>>>>>>>>>>> case we want to handle, I don't think it is needed.
>>>>>>>>>>> 4. There is another case you didn't list where the EMF can be
>> there
>>>>>> but
>>>>>>>>>> no
>>>>>>>>>>> EM and enhancement should happen ASAP: deserialization ;)
>>>>>>>>>>> 5. Finally there is a subtle difference between SE and EE case
>>>> where
>>>>>>>> one
>>>>>>>>>>> will trigger the agent and the other will just add the
>> transformer
>>>> in
>>>>>>>> the
>>>>>>>>>>> classloader through PersistenUnitInfo (and container should
>> handle
>>>>>> this
>>>>>>>>>>> additional properly), I don't know if our agent should be
>>>> compatible
>>>>>>>> with
>>>>>>>>>>> it for apploader (jvm one).
>>>>>>>>>>> 
>>>>>>>>>>> Romain Manni-Bucau
>>>>>>>>>>> @rmannibucau <https://twitter.com/rmannibucau> |  Blog
>>>>>>>>>>> <https://rmannibucau.metawerx.net/> | Old Blog
>>>>>>>>>>> <http://rmannibucau.wordpress.com> | Github <
>>>>>>>>>> https://github.com/rmannibucau> |
>>>>>>>>>>> LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
>>>>>>>>>>> <
>>>>>>>>>> 
>>>>>>>> 
>>>>>> 
>>>> 
>> https://www.packtpub.com/application-development/java-ee-8-high-performance
>>>>>>>>>>> 
>>>>>>>>>>> 
>>>>>>>>>>> 
>>>>>>>>>>> Le ven. 17 juil. 2020 à 09:35, Mark Struberg
>>>>>> <struberg@yahoo.de.invalid
>>>>>>>>> 
>>>>>>>>>> a
>>>>>>>>>>> écrit :
>>>>>>>>>>> 
>>>>>>>>>>>> hi folks!
>>>>>>>>>>>> 
>>>>>>>>>>>> I'm right now cleaning up old code in our enhancer. Like
>> removing
>>>>>>>> java5
>>>>>>>>>>>> hacks, etc
>>>>>>>>>>>> This is also triggered by our recent discussion about _transform
>>>> and
>>>>>>>>>> other
>>>>>>>>>>>> pieces.
>>>>>>>>>>>> Slowly getting my head into the right space for it. This is way
>>>> more
>>>>>>>>>>>> complex than I remembered ;)
>>>>>>>>>>>> 
>>>>>>>>>>>> So here is my next puzzle:
>>>>>>>>>>>> 
>>>>>>>>>>>> I've created a new example with 2 classes: Person and Employee
>>>>>> extends
>>>>>>>>>>>> Person
>>>>>>>>>>>> Plus a persistence.xml with enlisting those 2 classes (makes a
>>>>>>>>>>>> difference!) and essentially
>>>>>>>>>>>> <property name="openjpa.DynamicEnhancementAgent" value="true"/>
>>>>>>>>>>>> <property name="openjpa.RuntimeUnenhancedClasses"
>>>>>> value="supported"/>
>>>>>>>>>>>> The reason I switched on RuntimeUnenhancedClasses is that this
>>>> check
>>>>>>>> is
>>>>>>>>>>>> performed when the BrokerFactory gets created.
>>>>>>>>>>>> And if the classes are not build-time enhanced, then it fails in
>>>>>>>>>>>> 
>>>>>>>>>> 
>>>>>>>> 
>>>>>> 
>>>> 
>> org.apache.openjpa.enhance.ManagedClassSubclasser#prepareUnenhancedClasses
>>>>>>>>>>>> if (conf.getRuntimeUnenhancedClassesConstant() !=
>>>>>>>>>>>> RuntimeUnenhancedClassesModes.SUPPORTED) { ..
>>>>>>>>>>>> And if you switch to supported, then it will create a new
>> subclass
>>>>>> and
>>>>>>>>>>>> replaces field access to the getters/setters. Sadly
>>>>>>>>>>>> java.lang.instrument.Instrumentation#retransform cannot be used
>> to
>>>>>> add
>>>>>>>>>> new
>>>>>>>>>>>> fields or methods. Otherwise we could do a direct full
>> replacement
>>>>>> of
>>>>>>>>>> this
>>>>>>>>>>>> class.
>>>>>>>>>>>> 
>>>>>>>>>>>> Fun thing is that later on in
>>>>>>>>>>>> 
>>>>>>>>>> 
>>>>>>>> 
>>>>>> 
>>>> 
>> org.apache.openjpa.persistence.PersistenceProviderImpl#createEntityManagerFactory(java.lang.String,
>>>>>>>>>>>> java.lang.String, java.util.Map)
>>>>>>>>>>>> we call loadAgent(factory);
>>>>>>>>>>>> But what is it supposed to do? Which cases does it serve?
>>>>>>>>>>>> If the classes did not have been already enhanced at build time
>>>> nor
>>>>>>>> via
>>>>>>>>>>>> javaagent they will now be subclassed by ManagedClassSubclasser.
>>>>>>>>>>>> And if we do not set RuntimeUnenhancedClasses=supported then we
>>>> will
>>>>>>>>>> never
>>>>>>>>>>>> make it so far but blow up way earlier.
>>>>>>>>>>>> 
>>>>>>>>>>>> Also: it is nice to have that agent attached. But why? All the
>>>>>> entity
>>>>>>>>>>>> classe already have been loaded already during BrokerFactory
>>>>>> startup.
>>>>>>>>>> There
>>>>>>>>>>>> is no more entity class left over which needs enhancement,
>> isn't?
>>>>>>>>>>>> 
>>>>>>>>>>>> This is the log I get which reflects what I mean. Happy to share
>>>> the
>>>>>>>>>> code
>>>>>>>>>>>> in a playground branch.
>>>>>>>>>>>> 
>>>>>>>>>>>> 1261  test-classtransform  INFO   [main] openjpa.Enhance -
>>>> Creating
>>>>>>>>>>>> subclass and redefining methods for "[class
>>>>>>>>>>>> org.apache.openjpa.examples.dynenhance.Employee, class
>>>>>>>>>>>> org.apache.openjpa.examples.dynenhance.Person]". This means that
>>>>>> your
>>>>>>>>>>>> application will be less efficient than it would if you ran the
>>>>>>>> OpenJPA
>>>>>>>>>>>> enhancer.
>>>>>>>>>>>> 1412  test-classtransform  INFO   [main] openjpa.Runtime -
>> OpenJPA
>>>>>>>>>>>> dynamically loaded the class enhancer. Any classes that were not
>>>>>>>>>> enhanced
>>>>>>>>>>>> at build time will be enhanced when they are loaded by the JVM.
>>>>>>>>>>>> 
>>>>>>>>>>>> 
>>>>>>>>>>>> LieGrue,
>>>>>>>>>>>> strub
>>>>>> 
>>>>>> 
>>>> 
>>>> 
>> 
>> 


Re: A few runtime enhancement/bytecode questions

Posted by Romain Manni-Bucau <rm...@gmail.com>.
Le dim. 19 juil. 2020 à 00:47, Mark Struberg <st...@yahoo.de.invalid> a
écrit :

> Yes, it seems that the recursive call is just from using an openjpa class
> when the first javaagent transformer starts it's work.
> That means before any openjpa code is actually used. This _could_ be
> prevented if the premain code in the agent would touch all the necessary
> classes. But of course this is error prone as well.
>

Not in EE case where enhancer classes will be loaded by the transformer and
never the agent.
Also can not be with a custom openjpa spi loading classes (if we exclude
this case, im for it, we should write it in our doc somewhere probably just
to not forget again).


> For any entity etc it will not be called recursively. The
> java.lang.instrument.ClassFileTransformer#transform method just returns a
> byte[] with the new bytecode. But it does not interpret that bytecode
> during transformation. Thus no recursive call.
>

Well it can with asm but using tmploader so until you do like me in
embedded case (or optim in tomee), apploader=tmploader + cds, to save a lot
of time, then it works.

We could use a ThreadLocal<AtomicBoolean> and even set it to null after the
> first run. Because once openjpa is initted we should not see any recursive
> invocations anymore. Something like that.
>

Also means we dont need that and can just exclude openjpa stack as i
proposed whicj makes the method "pure" which is saner and like as fast in
general case (in terms of complexity).
So sounds saner.


> LieGrue,
> strub
>
> > Am 18.07.2020 um 18:18 schrieb Romain Manni-Bucau <rmannibucau@gmail.com
> >:
> >
> > Oh just got it, you need to extend openjpa (MDR for ex) otherwise it does
> > only happen if openjpa is not loaded during the enhancement, which means
> > the javaagent is there, the entity is loaded but the EMF not yet there,
> so
> > 2 cases (even if one is unlikely but can happen due to our spi).
> >
> > Romain Manni-Bucau
> > @rmannibucau <https://twitter.com/rmannibucau> |  Blog
> > <https://rmannibucau.metawerx.net/> | Old Blog
> > <http://rmannibucau.wordpress.com> | Github <
> https://github.com/rmannibucau> |
> > LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
> > <
> https://www.packtpub.com/application-development/java-ee-8-high-performance
> >
> >
> >
> > Le sam. 18 juil. 2020 à 18:07, Mark Struberg <st...@yahoo.de.invalid>
> a
> > écrit :
> >
> >> no, didn't work.
> >>
> >> LieGrue,
> >> strub
> >>
> >>
> >>> Am 18.07.2020 um 18:00 schrieb Romain Manni-Bucau <
> rmannibucau@gmail.com
> >>> :
> >>>
> >>> Not sure I got the question but I suspect the case can be reproduced
> >> with a
> >>> plain new MyEntity() before your Persistence.createEMF.
> >>>
> >>> Romain Manni-Bucau
> >>> @rmannibucau <https://twitter.com/rmannibucau> |  Blog
> >>> <https://rmannibucau.metawerx.net/> | Old Blog
> >>> <http://rmannibucau.wordpress.com> | Github <
> >> https://github.com/rmannibucau> |
> >>> LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
> >>> <
> >>
> https://www.packtpub.com/application-development/java-ee-8-high-performance
> >>>
> >>>
> >>>
> >>> Le sam. 18 juil. 2020 à 17:57, Mark Struberg <struberg@yahoo.de.invalid
> >
> >> a
> >>> écrit :
> >>>
> >>>> Found it yesterday when reviewing my sample with Romain:
> >>>>
> >>>> I apparently did copy the following property over from another
> example:
> >>>> <property name="openjpa.InitializeEagerly" value="true"/>
> >>>> And this did lead to already trigger the class transformation while
> >>>> createEntityManagerFactory.
> >>>>
> >>>> I did create a few samples, but did not manage to trigger any
> subsequent
> >>>> classloading at all. So no wonder in which case this could hit us yet.
> >>>> Before we introduce another expensive mechanism I would love to
> >> understand
> >>>> when the situation occurs at all.
> >>>>
> >>>> LieGrue,
> >>>> strub
> >>>>
> >>>>
> >>>>
> >>>>
> >>>>
> >>>>> Am 17.07.2020 um 12:03 schrieb Romain Manni-Bucau <
> >> rmannibucau@gmail.com
> >>>>> :
> >>>>>
> >>>>> Le ven. 17 juil. 2020 à 11:27, Mark Struberg
> <struberg@yahoo.de.invalid
> >>>> <ma...@yahoo.de.invalid>> a
> >>>>> écrit :
> >>>>>
> >>>>>> answers inside.
> >>>>>>
> >>>>>> LieGrue,
> >>>>>> strub
> >>>>>>
> >>>>>>> Am 17.07.2020 um 11:14 schrieb Romain Manni-Bucau <
> >>>> rmannibucau@gmail.com
> >>>>>>> :
> >>>>>>>
> >>>>>>> Le ven. 17 juil. 2020 à 10:45, Mark Struberg
> >> <struberg@yahoo.de.invalid
> >>>>>
> >>>>>> a
> >>>>>>> écrit :
> >>>>>>>
> >>>>>>>> Both prepareUnenhancedClasses and loadAgent already run in
> >>>>>>>> createEntityManagerFactory.
> >>>>>>>>
> >>>>>>>
> >>>>>>> Not in general, depends the conf and by default i run in none of
> both
> >>>>>> with
> >>>>>>> a standard config for ex for EE.
> >>>>>>
> >>>>>> Let me rephrase this: both those methods will get called in
> >>>>>> createEntityManagerFactory already. If they actually perform some
> >>>> bytecode
> >>>>>> enhancement is up to configuration and whether the classes have been
> >>>>>> enhanced otherwise before ;)
> >>>>>>
> >>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>> crateEntityManager does not trigger enhancement afaict.
> >>>>>>>>
> >>>>>>>
> >>>>>>> createEMF does not since the creation of openjpa is lazy so the
> first
> >>>>>>> createEM does (in general case one again).
> >>>>>>
> >>>>>> Nope, it really gets called already by createEntityManagerFactory.
> You
> >>>> can
> >>>>>> debug into this if you want.
> >>>>>>
> >>>>>
> >>>>> Did and I can guarantee you it is lazy if your conf does not enforce
> it
> >>>>> somehow.
> >>>>>
> >>>>>
> >>>>>>
> >>>>>> LieGrue,
> >>>>>> strub
> >>>>>>
> >>>>>>
> >>>>>>>
> >>>>>>>>
> >>>>>>>> LieGrue,
> >>>>>>>> strub
> >>>>>>>>
> >>>>>>>>> Am 17.07.2020 um 10:11 schrieb Romain Manni-Bucau <
> >>>>>> rmannibucau@gmail.com
> >>>>>>>>> :
> >>>>>>>>>
> >>>>>>>>> Hi Mark,
> >>>>>>>>>
> >>>>>>>>> If it helps:
> >>>>>>>>>
> >>>>>>>>> 1.
> >>>> org.apache.openjpa.kernel.AbstractBrokerFactory#postCreationCallback
> >>>>>>>>> only triggers the prepareUnenhancedClasses if preload=true (never
> >> the
> >>>>>>>> case
> >>>>>>>>> right? ;))
> >>>>>>>>> 2. Normally classes are loaded in
> >>>>>>>>> there
> >>>> org.apache.openjpa.kernel.AbstractBrokerFactory#initializeBroker
> >>>>>>>>> *when creating an em, not an emf* so better to have loaded ran
> the
> >>>>>>>>> enhancement early (loadAgent)
> >>>>>>>>> 3. Not sure it is done but it can happen 2 has a custom MDR not
> >>>>>> returning
> >>>>>>>>> right the classes - seems code is ok with that. I don't know if
> it
> >>>> is a
> >>>>>>>>> case we want to handle, I don't think it is needed.
> >>>>>>>>> 4. There is another case you didn't list where the EMF can be
> there
> >>>> but
> >>>>>>>> no
> >>>>>>>>> EM and enhancement should happen ASAP: deserialization ;)
> >>>>>>>>> 5. Finally there is a subtle difference between SE and EE case
> >> where
> >>>>>> one
> >>>>>>>>> will trigger the agent and the other will just add the
> transformer
> >> in
> >>>>>> the
> >>>>>>>>> classloader through PersistenUnitInfo (and container should
> handle
> >>>> this
> >>>>>>>>> additional properly), I don't know if our agent should be
> >> compatible
> >>>>>> with
> >>>>>>>>> it for apploader (jvm one).
> >>>>>>>>>
> >>>>>>>>> Romain Manni-Bucau
> >>>>>>>>> @rmannibucau <https://twitter.com/rmannibucau> |  Blog
> >>>>>>>>> <https://rmannibucau.metawerx.net/> | Old Blog
> >>>>>>>>> <http://rmannibucau.wordpress.com> | Github <
> >>>>>>>> https://github.com/rmannibucau> |
> >>>>>>>>> LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
> >>>>>>>>> <
> >>>>>>>>
> >>>>>>
> >>>>
> >>
> https://www.packtpub.com/application-development/java-ee-8-high-performance
> >>>>>>>>>
> >>>>>>>>>
> >>>>>>>>>
> >>>>>>>>> Le ven. 17 juil. 2020 à 09:35, Mark Struberg
> >>>> <struberg@yahoo.de.invalid
> >>>>>>>
> >>>>>>>> a
> >>>>>>>>> écrit :
> >>>>>>>>>
> >>>>>>>>>> hi folks!
> >>>>>>>>>>
> >>>>>>>>>> I'm right now cleaning up old code in our enhancer. Like
> removing
> >>>>>> java5
> >>>>>>>>>> hacks, etc
> >>>>>>>>>> This is also triggered by our recent discussion about _transform
> >> and
> >>>>>>>> other
> >>>>>>>>>> pieces.
> >>>>>>>>>> Slowly getting my head into the right space for it. This is way
> >> more
> >>>>>>>>>> complex than I remembered ;)
> >>>>>>>>>>
> >>>>>>>>>> So here is my next puzzle:
> >>>>>>>>>>
> >>>>>>>>>> I've created a new example with 2 classes: Person and Employee
> >>>> extends
> >>>>>>>>>> Person
> >>>>>>>>>> Plus a persistence.xml with enlisting those 2 classes (makes a
> >>>>>>>>>> difference!) and essentially
> >>>>>>>>>> <property name="openjpa.DynamicEnhancementAgent" value="true"/>
> >>>>>>>>>> <property name="openjpa.RuntimeUnenhancedClasses"
> >>>> value="supported"/>
> >>>>>>>>>> The reason I switched on RuntimeUnenhancedClasses is that this
> >> check
> >>>>>> is
> >>>>>>>>>> performed when the BrokerFactory gets created.
> >>>>>>>>>> And if the classes are not build-time enhanced, then it fails in
> >>>>>>>>>>
> >>>>>>>>
> >>>>>>
> >>>>
> >>
> org.apache.openjpa.enhance.ManagedClassSubclasser#prepareUnenhancedClasses
> >>>>>>>>>> if (conf.getRuntimeUnenhancedClassesConstant() !=
> >>>>>>>>>> RuntimeUnenhancedClassesModes.SUPPORTED) { ..
> >>>>>>>>>> And if you switch to supported, then it will create a new
> subclass
> >>>> and
> >>>>>>>>>> replaces field access to the getters/setters. Sadly
> >>>>>>>>>> java.lang.instrument.Instrumentation#retransform cannot be used
> to
> >>>> add
> >>>>>>>> new
> >>>>>>>>>> fields or methods. Otherwise we could do a direct full
> replacement
> >>>> of
> >>>>>>>> this
> >>>>>>>>>> class.
> >>>>>>>>>>
> >>>>>>>>>> Fun thing is that later on in
> >>>>>>>>>>
> >>>>>>>>
> >>>>>>
> >>>>
> >>
> org.apache.openjpa.persistence.PersistenceProviderImpl#createEntityManagerFactory(java.lang.String,
> >>>>>>>>>> java.lang.String, java.util.Map)
> >>>>>>>>>> we call loadAgent(factory);
> >>>>>>>>>> But what is it supposed to do? Which cases does it serve?
> >>>>>>>>>> If the classes did not have been already enhanced at build time
> >> nor
> >>>>>> via
> >>>>>>>>>> javaagent they will now be subclassed by ManagedClassSubclasser.
> >>>>>>>>>> And if we do not set RuntimeUnenhancedClasses=supported then we
> >> will
> >>>>>>>> never
> >>>>>>>>>> make it so far but blow up way earlier.
> >>>>>>>>>>
> >>>>>>>>>> Also: it is nice to have that agent attached. But why? All the
> >>>> entity
> >>>>>>>>>> classe already have been loaded already during BrokerFactory
> >>>> startup.
> >>>>>>>> There
> >>>>>>>>>> is no more entity class left over which needs enhancement,
> isn't?
> >>>>>>>>>>
> >>>>>>>>>> This is the log I get which reflects what I mean. Happy to share
> >> the
> >>>>>>>> code
> >>>>>>>>>> in a playground branch.
> >>>>>>>>>>
> >>>>>>>>>> 1261  test-classtransform  INFO   [main] openjpa.Enhance -
> >> Creating
> >>>>>>>>>> subclass and redefining methods for "[class
> >>>>>>>>>> org.apache.openjpa.examples.dynenhance.Employee, class
> >>>>>>>>>> org.apache.openjpa.examples.dynenhance.Person]". This means that
> >>>> your
> >>>>>>>>>> application will be less efficient than it would if you ran the
> >>>>>> OpenJPA
> >>>>>>>>>> enhancer.
> >>>>>>>>>> 1412  test-classtransform  INFO   [main] openjpa.Runtime -
> OpenJPA
> >>>>>>>>>> dynamically loaded the class enhancer. Any classes that were not
> >>>>>>>> enhanced
> >>>>>>>>>> at build time will be enhanced when they are loaded by the JVM.
> >>>>>>>>>>
> >>>>>>>>>>
> >>>>>>>>>> LieGrue,
> >>>>>>>>>> strub
> >>>>
> >>>>
> >>
> >>
>
>

Re: A few runtime enhancement/bytecode questions

Posted by Mark Struberg <st...@yahoo.de.INVALID>.
Yes, it seems that the recursive call is just from using an openjpa class when the first javaagent transformer starts it's work.
That means before any openjpa code is actually used. This _could_ be prevented if the premain code in the agent would touch all the necessary classes. But of course this is error prone as well.

For any entity etc it will not be called recursively. The java.lang.instrument.ClassFileTransformer#transform method just returns a byte[] with the new bytecode. But it does not interpret that bytecode during transformation. Thus no recursive call.
We could use a ThreadLocal<AtomicBoolean> and even set it to null after the first run. Because once openjpa is initted we should not see any recursive invocations anymore. Something like that.

LieGrue,
strub

> Am 18.07.2020 um 18:18 schrieb Romain Manni-Bucau <rm...@gmail.com>:
> 
> Oh just got it, you need to extend openjpa (MDR for ex) otherwise it does
> only happen if openjpa is not loaded during the enhancement, which means
> the javaagent is there, the entity is loaded but the EMF not yet there, so
> 2 cases (even if one is unlikely but can happen due to our spi).
> 
> Romain Manni-Bucau
> @rmannibucau <https://twitter.com/rmannibucau> |  Blog
> <https://rmannibucau.metawerx.net/> | Old Blog
> <http://rmannibucau.wordpress.com> | Github <https://github.com/rmannibucau> |
> LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
> <https://www.packtpub.com/application-development/java-ee-8-high-performance>
> 
> 
> Le sam. 18 juil. 2020 à 18:07, Mark Struberg <st...@yahoo.de.invalid> a
> écrit :
> 
>> no, didn't work.
>> 
>> LieGrue,
>> strub
>> 
>> 
>>> Am 18.07.2020 um 18:00 schrieb Romain Manni-Bucau <rmannibucau@gmail.com
>>> :
>>> 
>>> Not sure I got the question but I suspect the case can be reproduced
>> with a
>>> plain new MyEntity() before your Persistence.createEMF.
>>> 
>>> Romain Manni-Bucau
>>> @rmannibucau <https://twitter.com/rmannibucau> |  Blog
>>> <https://rmannibucau.metawerx.net/> | Old Blog
>>> <http://rmannibucau.wordpress.com> | Github <
>> https://github.com/rmannibucau> |
>>> LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
>>> <
>> https://www.packtpub.com/application-development/java-ee-8-high-performance
>>> 
>>> 
>>> 
>>> Le sam. 18 juil. 2020 à 17:57, Mark Struberg <st...@yahoo.de.invalid>
>> a
>>> écrit :
>>> 
>>>> Found it yesterday when reviewing my sample with Romain:
>>>> 
>>>> I apparently did copy the following property over from another example:
>>>> <property name="openjpa.InitializeEagerly" value="true"/>
>>>> And this did lead to already trigger the class transformation while
>>>> createEntityManagerFactory.
>>>> 
>>>> I did create a few samples, but did not manage to trigger any subsequent
>>>> classloading at all. So no wonder in which case this could hit us yet.
>>>> Before we introduce another expensive mechanism I would love to
>> understand
>>>> when the situation occurs at all.
>>>> 
>>>> LieGrue,
>>>> strub
>>>> 
>>>> 
>>>> 
>>>> 
>>>> 
>>>>> Am 17.07.2020 um 12:03 schrieb Romain Manni-Bucau <
>> rmannibucau@gmail.com
>>>>> :
>>>>> 
>>>>> Le ven. 17 juil. 2020 à 11:27, Mark Struberg <struberg@yahoo.de.invalid
>>>> <ma...@yahoo.de.invalid>> a
>>>>> écrit :
>>>>> 
>>>>>> answers inside.
>>>>>> 
>>>>>> LieGrue,
>>>>>> strub
>>>>>> 
>>>>>>> Am 17.07.2020 um 11:14 schrieb Romain Manni-Bucau <
>>>> rmannibucau@gmail.com
>>>>>>> :
>>>>>>> 
>>>>>>> Le ven. 17 juil. 2020 à 10:45, Mark Struberg
>> <struberg@yahoo.de.invalid
>>>>> 
>>>>>> a
>>>>>>> écrit :
>>>>>>> 
>>>>>>>> Both prepareUnenhancedClasses and loadAgent already run in
>>>>>>>> createEntityManagerFactory.
>>>>>>>> 
>>>>>>> 
>>>>>>> Not in general, depends the conf and by default i run in none of both
>>>>>> with
>>>>>>> a standard config for ex for EE.
>>>>>> 
>>>>>> Let me rephrase this: both those methods will get called in
>>>>>> createEntityManagerFactory already. If they actually perform some
>>>> bytecode
>>>>>> enhancement is up to configuration and whether the classes have been
>>>>>> enhanced otherwise before ;)
>>>>>> 
>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>>> crateEntityManager does not trigger enhancement afaict.
>>>>>>>> 
>>>>>>> 
>>>>>>> createEMF does not since the creation of openjpa is lazy so the first
>>>>>>> createEM does (in general case one again).
>>>>>> 
>>>>>> Nope, it really gets called already by createEntityManagerFactory. You
>>>> can
>>>>>> debug into this if you want.
>>>>>> 
>>>>> 
>>>>> Did and I can guarantee you it is lazy if your conf does not enforce it
>>>>> somehow.
>>>>> 
>>>>> 
>>>>>> 
>>>>>> LieGrue,
>>>>>> strub
>>>>>> 
>>>>>> 
>>>>>>> 
>>>>>>>> 
>>>>>>>> LieGrue,
>>>>>>>> strub
>>>>>>>> 
>>>>>>>>> Am 17.07.2020 um 10:11 schrieb Romain Manni-Bucau <
>>>>>> rmannibucau@gmail.com
>>>>>>>>> :
>>>>>>>>> 
>>>>>>>>> Hi Mark,
>>>>>>>>> 
>>>>>>>>> If it helps:
>>>>>>>>> 
>>>>>>>>> 1.
>>>> org.apache.openjpa.kernel.AbstractBrokerFactory#postCreationCallback
>>>>>>>>> only triggers the prepareUnenhancedClasses if preload=true (never
>> the
>>>>>>>> case
>>>>>>>>> right? ;))
>>>>>>>>> 2. Normally classes are loaded in
>>>>>>>>> there
>>>> org.apache.openjpa.kernel.AbstractBrokerFactory#initializeBroker
>>>>>>>>> *when creating an em, not an emf* so better to have loaded ran the
>>>>>>>>> enhancement early (loadAgent)
>>>>>>>>> 3. Not sure it is done but it can happen 2 has a custom MDR not
>>>>>> returning
>>>>>>>>> right the classes - seems code is ok with that. I don't know if it
>>>> is a
>>>>>>>>> case we want to handle, I don't think it is needed.
>>>>>>>>> 4. There is another case you didn't list where the EMF can be there
>>>> but
>>>>>>>> no
>>>>>>>>> EM and enhancement should happen ASAP: deserialization ;)
>>>>>>>>> 5. Finally there is a subtle difference between SE and EE case
>> where
>>>>>> one
>>>>>>>>> will trigger the agent and the other will just add the transformer
>> in
>>>>>> the
>>>>>>>>> classloader through PersistenUnitInfo (and container should handle
>>>> this
>>>>>>>>> additional properly), I don't know if our agent should be
>> compatible
>>>>>> with
>>>>>>>>> it for apploader (jvm one).
>>>>>>>>> 
>>>>>>>>> Romain Manni-Bucau
>>>>>>>>> @rmannibucau <https://twitter.com/rmannibucau> |  Blog
>>>>>>>>> <https://rmannibucau.metawerx.net/> | Old Blog
>>>>>>>>> <http://rmannibucau.wordpress.com> | Github <
>>>>>>>> https://github.com/rmannibucau> |
>>>>>>>>> LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
>>>>>>>>> <
>>>>>>>> 
>>>>>> 
>>>> 
>> https://www.packtpub.com/application-development/java-ee-8-high-performance
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> Le ven. 17 juil. 2020 à 09:35, Mark Struberg
>>>> <struberg@yahoo.de.invalid
>>>>>>> 
>>>>>>>> a
>>>>>>>>> écrit :
>>>>>>>>> 
>>>>>>>>>> hi folks!
>>>>>>>>>> 
>>>>>>>>>> I'm right now cleaning up old code in our enhancer. Like removing
>>>>>> java5
>>>>>>>>>> hacks, etc
>>>>>>>>>> This is also triggered by our recent discussion about _transform
>> and
>>>>>>>> other
>>>>>>>>>> pieces.
>>>>>>>>>> Slowly getting my head into the right space for it. This is way
>> more
>>>>>>>>>> complex than I remembered ;)
>>>>>>>>>> 
>>>>>>>>>> So here is my next puzzle:
>>>>>>>>>> 
>>>>>>>>>> I've created a new example with 2 classes: Person and Employee
>>>> extends
>>>>>>>>>> Person
>>>>>>>>>> Plus a persistence.xml with enlisting those 2 classes (makes a
>>>>>>>>>> difference!) and essentially
>>>>>>>>>> <property name="openjpa.DynamicEnhancementAgent" value="true"/>
>>>>>>>>>> <property name="openjpa.RuntimeUnenhancedClasses"
>>>> value="supported"/>
>>>>>>>>>> The reason I switched on RuntimeUnenhancedClasses is that this
>> check
>>>>>> is
>>>>>>>>>> performed when the BrokerFactory gets created.
>>>>>>>>>> And if the classes are not build-time enhanced, then it fails in
>>>>>>>>>> 
>>>>>>>> 
>>>>>> 
>>>> 
>> org.apache.openjpa.enhance.ManagedClassSubclasser#prepareUnenhancedClasses
>>>>>>>>>> if (conf.getRuntimeUnenhancedClassesConstant() !=
>>>>>>>>>> RuntimeUnenhancedClassesModes.SUPPORTED) { ..
>>>>>>>>>> And if you switch to supported, then it will create a new subclass
>>>> and
>>>>>>>>>> replaces field access to the getters/setters. Sadly
>>>>>>>>>> java.lang.instrument.Instrumentation#retransform cannot be used to
>>>> add
>>>>>>>> new
>>>>>>>>>> fields or methods. Otherwise we could do a direct full replacement
>>>> of
>>>>>>>> this
>>>>>>>>>> class.
>>>>>>>>>> 
>>>>>>>>>> Fun thing is that later on in
>>>>>>>>>> 
>>>>>>>> 
>>>>>> 
>>>> 
>> org.apache.openjpa.persistence.PersistenceProviderImpl#createEntityManagerFactory(java.lang.String,
>>>>>>>>>> java.lang.String, java.util.Map)
>>>>>>>>>> we call loadAgent(factory);
>>>>>>>>>> But what is it supposed to do? Which cases does it serve?
>>>>>>>>>> If the classes did not have been already enhanced at build time
>> nor
>>>>>> via
>>>>>>>>>> javaagent they will now be subclassed by ManagedClassSubclasser.
>>>>>>>>>> And if we do not set RuntimeUnenhancedClasses=supported then we
>> will
>>>>>>>> never
>>>>>>>>>> make it so far but blow up way earlier.
>>>>>>>>>> 
>>>>>>>>>> Also: it is nice to have that agent attached. But why? All the
>>>> entity
>>>>>>>>>> classe already have been loaded already during BrokerFactory
>>>> startup.
>>>>>>>> There
>>>>>>>>>> is no more entity class left over which needs enhancement, isn't?
>>>>>>>>>> 
>>>>>>>>>> This is the log I get which reflects what I mean. Happy to share
>> the
>>>>>>>> code
>>>>>>>>>> in a playground branch.
>>>>>>>>>> 
>>>>>>>>>> 1261  test-classtransform  INFO   [main] openjpa.Enhance -
>> Creating
>>>>>>>>>> subclass and redefining methods for "[class
>>>>>>>>>> org.apache.openjpa.examples.dynenhance.Employee, class
>>>>>>>>>> org.apache.openjpa.examples.dynenhance.Person]". This means that
>>>> your
>>>>>>>>>> application will be less efficient than it would if you ran the
>>>>>> OpenJPA
>>>>>>>>>> enhancer.
>>>>>>>>>> 1412  test-classtransform  INFO   [main] openjpa.Runtime - OpenJPA
>>>>>>>>>> dynamically loaded the class enhancer. Any classes that were not
>>>>>>>> enhanced
>>>>>>>>>> at build time will be enhanced when they are loaded by the JVM.
>>>>>>>>>> 
>>>>>>>>>> 
>>>>>>>>>> LieGrue,
>>>>>>>>>> strub
>>>> 
>>>> 
>> 
>> 


Re: A few runtime enhancement/bytecode questions

Posted by Romain Manni-Bucau <rm...@gmail.com>.
Oh just got it, you need to extend openjpa (MDR for ex) otherwise it does
only happen if openjpa is not loaded during the enhancement, which means
the javaagent is there, the entity is loaded but the EMF not yet there, so
2 cases (even if one is unlikely but can happen due to our spi).

Romain Manni-Bucau
@rmannibucau <https://twitter.com/rmannibucau> |  Blog
<https://rmannibucau.metawerx.net/> | Old Blog
<http://rmannibucau.wordpress.com> | Github <https://github.com/rmannibucau> |
LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
<https://www.packtpub.com/application-development/java-ee-8-high-performance>


Le sam. 18 juil. 2020 à 18:07, Mark Struberg <st...@yahoo.de.invalid> a
écrit :

> no, didn't work.
>
> LieGrue,
> strub
>
>
> > Am 18.07.2020 um 18:00 schrieb Romain Manni-Bucau <rmannibucau@gmail.com
> >:
> >
> > Not sure I got the question but I suspect the case can be reproduced
> with a
> > plain new MyEntity() before your Persistence.createEMF.
> >
> > Romain Manni-Bucau
> > @rmannibucau <https://twitter.com/rmannibucau> |  Blog
> > <https://rmannibucau.metawerx.net/> | Old Blog
> > <http://rmannibucau.wordpress.com> | Github <
> https://github.com/rmannibucau> |
> > LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
> > <
> https://www.packtpub.com/application-development/java-ee-8-high-performance
> >
> >
> >
> > Le sam. 18 juil. 2020 à 17:57, Mark Struberg <st...@yahoo.de.invalid>
> a
> > écrit :
> >
> >> Found it yesterday when reviewing my sample with Romain:
> >>
> >> I apparently did copy the following property over from another example:
> >> <property name="openjpa.InitializeEagerly" value="true"/>
> >> And this did lead to already trigger the class transformation while
> >> createEntityManagerFactory.
> >>
> >> I did create a few samples, but did not manage to trigger any subsequent
> >> classloading at all. So no wonder in which case this could hit us yet.
> >> Before we introduce another expensive mechanism I would love to
> understand
> >> when the situation occurs at all.
> >>
> >> LieGrue,
> >> strub
> >>
> >>
> >>
> >>
> >>
> >>> Am 17.07.2020 um 12:03 schrieb Romain Manni-Bucau <
> rmannibucau@gmail.com
> >>> :
> >>>
> >>> Le ven. 17 juil. 2020 à 11:27, Mark Struberg <struberg@yahoo.de.invalid
> >> <ma...@yahoo.de.invalid>> a
> >>> écrit :
> >>>
> >>>> answers inside.
> >>>>
> >>>> LieGrue,
> >>>> strub
> >>>>
> >>>>> Am 17.07.2020 um 11:14 schrieb Romain Manni-Bucau <
> >> rmannibucau@gmail.com
> >>>>> :
> >>>>>
> >>>>> Le ven. 17 juil. 2020 à 10:45, Mark Struberg
> <struberg@yahoo.de.invalid
> >>>
> >>>> a
> >>>>> écrit :
> >>>>>
> >>>>>> Both prepareUnenhancedClasses and loadAgent already run in
> >>>>>> createEntityManagerFactory.
> >>>>>>
> >>>>>
> >>>>> Not in general, depends the conf and by default i run in none of both
> >>>> with
> >>>>> a standard config for ex for EE.
> >>>>
> >>>> Let me rephrase this: both those methods will get called in
> >>>> createEntityManagerFactory already. If they actually perform some
> >> bytecode
> >>>> enhancement is up to configuration and whether the classes have been
> >>>> enhanced otherwise before ;)
> >>>>
> >>>>
> >>>>>
> >>>>>
> >>>>>> crateEntityManager does not trigger enhancement afaict.
> >>>>>>
> >>>>>
> >>>>> createEMF does not since the creation of openjpa is lazy so the first
> >>>>> createEM does (in general case one again).
> >>>>
> >>>> Nope, it really gets called already by createEntityManagerFactory. You
> >> can
> >>>> debug into this if you want.
> >>>>
> >>>
> >>> Did and I can guarantee you it is lazy if your conf does not enforce it
> >>> somehow.
> >>>
> >>>
> >>>>
> >>>> LieGrue,
> >>>> strub
> >>>>
> >>>>
> >>>>>
> >>>>>>
> >>>>>> LieGrue,
> >>>>>> strub
> >>>>>>
> >>>>>>> Am 17.07.2020 um 10:11 schrieb Romain Manni-Bucau <
> >>>> rmannibucau@gmail.com
> >>>>>>> :
> >>>>>>>
> >>>>>>> Hi Mark,
> >>>>>>>
> >>>>>>> If it helps:
> >>>>>>>
> >>>>>>> 1.
> >> org.apache.openjpa.kernel.AbstractBrokerFactory#postCreationCallback
> >>>>>>> only triggers the prepareUnenhancedClasses if preload=true (never
> the
> >>>>>> case
> >>>>>>> right? ;))
> >>>>>>> 2. Normally classes are loaded in
> >>>>>>> there
> >> org.apache.openjpa.kernel.AbstractBrokerFactory#initializeBroker
> >>>>>>> *when creating an em, not an emf* so better to have loaded ran the
> >>>>>>> enhancement early (loadAgent)
> >>>>>>> 3. Not sure it is done but it can happen 2 has a custom MDR not
> >>>> returning
> >>>>>>> right the classes - seems code is ok with that. I don't know if it
> >> is a
> >>>>>>> case we want to handle, I don't think it is needed.
> >>>>>>> 4. There is another case you didn't list where the EMF can be there
> >> but
> >>>>>> no
> >>>>>>> EM and enhancement should happen ASAP: deserialization ;)
> >>>>>>> 5. Finally there is a subtle difference between SE and EE case
> where
> >>>> one
> >>>>>>> will trigger the agent and the other will just add the transformer
> in
> >>>> the
> >>>>>>> classloader through PersistenUnitInfo (and container should handle
> >> this
> >>>>>>> additional properly), I don't know if our agent should be
> compatible
> >>>> with
> >>>>>>> it for apploader (jvm one).
> >>>>>>>
> >>>>>>> Romain Manni-Bucau
> >>>>>>> @rmannibucau <https://twitter.com/rmannibucau> |  Blog
> >>>>>>> <https://rmannibucau.metawerx.net/> | Old Blog
> >>>>>>> <http://rmannibucau.wordpress.com> | Github <
> >>>>>> https://github.com/rmannibucau> |
> >>>>>>> LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
> >>>>>>> <
> >>>>>>
> >>>>
> >>
> https://www.packtpub.com/application-development/java-ee-8-high-performance
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>> Le ven. 17 juil. 2020 à 09:35, Mark Struberg
> >> <struberg@yahoo.de.invalid
> >>>>>
> >>>>>> a
> >>>>>>> écrit :
> >>>>>>>
> >>>>>>>> hi folks!
> >>>>>>>>
> >>>>>>>> I'm right now cleaning up old code in our enhancer. Like removing
> >>>> java5
> >>>>>>>> hacks, etc
> >>>>>>>> This is also triggered by our recent discussion about _transform
> and
> >>>>>> other
> >>>>>>>> pieces.
> >>>>>>>> Slowly getting my head into the right space for it. This is way
> more
> >>>>>>>> complex than I remembered ;)
> >>>>>>>>
> >>>>>>>> So here is my next puzzle:
> >>>>>>>>
> >>>>>>>> I've created a new example with 2 classes: Person and Employee
> >> extends
> >>>>>>>> Person
> >>>>>>>> Plus a persistence.xml with enlisting those 2 classes (makes a
> >>>>>>>> difference!) and essentially
> >>>>>>>> <property name="openjpa.DynamicEnhancementAgent" value="true"/>
> >>>>>>>> <property name="openjpa.RuntimeUnenhancedClasses"
> >> value="supported"/>
> >>>>>>>> The reason I switched on RuntimeUnenhancedClasses is that this
> check
> >>>> is
> >>>>>>>> performed when the BrokerFactory gets created.
> >>>>>>>> And if the classes are not build-time enhanced, then it fails in
> >>>>>>>>
> >>>>>>
> >>>>
> >>
> org.apache.openjpa.enhance.ManagedClassSubclasser#prepareUnenhancedClasses
> >>>>>>>> if (conf.getRuntimeUnenhancedClassesConstant() !=
> >>>>>>>> RuntimeUnenhancedClassesModes.SUPPORTED) { ..
> >>>>>>>> And if you switch to supported, then it will create a new subclass
> >> and
> >>>>>>>> replaces field access to the getters/setters. Sadly
> >>>>>>>> java.lang.instrument.Instrumentation#retransform cannot be used to
> >> add
> >>>>>> new
> >>>>>>>> fields or methods. Otherwise we could do a direct full replacement
> >> of
> >>>>>> this
> >>>>>>>> class.
> >>>>>>>>
> >>>>>>>> Fun thing is that later on in
> >>>>>>>>
> >>>>>>
> >>>>
> >>
> org.apache.openjpa.persistence.PersistenceProviderImpl#createEntityManagerFactory(java.lang.String,
> >>>>>>>> java.lang.String, java.util.Map)
> >>>>>>>> we call loadAgent(factory);
> >>>>>>>> But what is it supposed to do? Which cases does it serve?
> >>>>>>>> If the classes did not have been already enhanced at build time
> nor
> >>>> via
> >>>>>>>> javaagent they will now be subclassed by ManagedClassSubclasser.
> >>>>>>>> And if we do not set RuntimeUnenhancedClasses=supported then we
> will
> >>>>>> never
> >>>>>>>> make it so far but blow up way earlier.
> >>>>>>>>
> >>>>>>>> Also: it is nice to have that agent attached. But why? All the
> >> entity
> >>>>>>>> classe already have been loaded already during BrokerFactory
> >> startup.
> >>>>>> There
> >>>>>>>> is no more entity class left over which needs enhancement, isn't?
> >>>>>>>>
> >>>>>>>> This is the log I get which reflects what I mean. Happy to share
> the
> >>>>>> code
> >>>>>>>> in a playground branch.
> >>>>>>>>
> >>>>>>>> 1261  test-classtransform  INFO   [main] openjpa.Enhance -
> Creating
> >>>>>>>> subclass and redefining methods for "[class
> >>>>>>>> org.apache.openjpa.examples.dynenhance.Employee, class
> >>>>>>>> org.apache.openjpa.examples.dynenhance.Person]". This means that
> >> your
> >>>>>>>> application will be less efficient than it would if you ran the
> >>>> OpenJPA
> >>>>>>>> enhancer.
> >>>>>>>> 1412  test-classtransform  INFO   [main] openjpa.Runtime - OpenJPA
> >>>>>>>> dynamically loaded the class enhancer. Any classes that were not
> >>>>>> enhanced
> >>>>>>>> at build time will be enhanced when they are loaded by the JVM.
> >>>>>>>>
> >>>>>>>>
> >>>>>>>> LieGrue,
> >>>>>>>> strub
> >>
> >>
>
>

Re: A few runtime enhancement/bytecode questions

Posted by Mark Struberg <st...@yahoo.de.INVALID>.
no, didn't work.

LieGrue,
strub


> Am 18.07.2020 um 18:00 schrieb Romain Manni-Bucau <rm...@gmail.com>:
> 
> Not sure I got the question but I suspect the case can be reproduced with a
> plain new MyEntity() before your Persistence.createEMF.
> 
> Romain Manni-Bucau
> @rmannibucau <https://twitter.com/rmannibucau> |  Blog
> <https://rmannibucau.metawerx.net/> | Old Blog
> <http://rmannibucau.wordpress.com> | Github <https://github.com/rmannibucau> |
> LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
> <https://www.packtpub.com/application-development/java-ee-8-high-performance>
> 
> 
> Le sam. 18 juil. 2020 à 17:57, Mark Struberg <st...@yahoo.de.invalid> a
> écrit :
> 
>> Found it yesterday when reviewing my sample with Romain:
>> 
>> I apparently did copy the following property over from another example:
>> <property name="openjpa.InitializeEagerly" value="true"/>
>> And this did lead to already trigger the class transformation while
>> createEntityManagerFactory.
>> 
>> I did create a few samples, but did not manage to trigger any subsequent
>> classloading at all. So no wonder in which case this could hit us yet.
>> Before we introduce another expensive mechanism I would love to understand
>> when the situation occurs at all.
>> 
>> LieGrue,
>> strub
>> 
>> 
>> 
>> 
>> 
>>> Am 17.07.2020 um 12:03 schrieb Romain Manni-Bucau <rmannibucau@gmail.com
>>> :
>>> 
>>> Le ven. 17 juil. 2020 à 11:27, Mark Struberg <struberg@yahoo.de.invalid
>> <ma...@yahoo.de.invalid>> a
>>> écrit :
>>> 
>>>> answers inside.
>>>> 
>>>> LieGrue,
>>>> strub
>>>> 
>>>>> Am 17.07.2020 um 11:14 schrieb Romain Manni-Bucau <
>> rmannibucau@gmail.com
>>>>> :
>>>>> 
>>>>> Le ven. 17 juil. 2020 à 10:45, Mark Struberg <struberg@yahoo.de.invalid
>>> 
>>>> a
>>>>> écrit :
>>>>> 
>>>>>> Both prepareUnenhancedClasses and loadAgent already run in
>>>>>> createEntityManagerFactory.
>>>>>> 
>>>>> 
>>>>> Not in general, depends the conf and by default i run in none of both
>>>> with
>>>>> a standard config for ex for EE.
>>>> 
>>>> Let me rephrase this: both those methods will get called in
>>>> createEntityManagerFactory already. If they actually perform some
>> bytecode
>>>> enhancement is up to configuration and whether the classes have been
>>>> enhanced otherwise before ;)
>>>> 
>>>> 
>>>>> 
>>>>> 
>>>>>> crateEntityManager does not trigger enhancement afaict.
>>>>>> 
>>>>> 
>>>>> createEMF does not since the creation of openjpa is lazy so the first
>>>>> createEM does (in general case one again).
>>>> 
>>>> Nope, it really gets called already by createEntityManagerFactory. You
>> can
>>>> debug into this if you want.
>>>> 
>>> 
>>> Did and I can guarantee you it is lazy if your conf does not enforce it
>>> somehow.
>>> 
>>> 
>>>> 
>>>> LieGrue,
>>>> strub
>>>> 
>>>> 
>>>>> 
>>>>>> 
>>>>>> LieGrue,
>>>>>> strub
>>>>>> 
>>>>>>> Am 17.07.2020 um 10:11 schrieb Romain Manni-Bucau <
>>>> rmannibucau@gmail.com
>>>>>>> :
>>>>>>> 
>>>>>>> Hi Mark,
>>>>>>> 
>>>>>>> If it helps:
>>>>>>> 
>>>>>>> 1.
>> org.apache.openjpa.kernel.AbstractBrokerFactory#postCreationCallback
>>>>>>> only triggers the prepareUnenhancedClasses if preload=true (never the
>>>>>> case
>>>>>>> right? ;))
>>>>>>> 2. Normally classes are loaded in
>>>>>>> there
>> org.apache.openjpa.kernel.AbstractBrokerFactory#initializeBroker
>>>>>>> *when creating an em, not an emf* so better to have loaded ran the
>>>>>>> enhancement early (loadAgent)
>>>>>>> 3. Not sure it is done but it can happen 2 has a custom MDR not
>>>> returning
>>>>>>> right the classes - seems code is ok with that. I don't know if it
>> is a
>>>>>>> case we want to handle, I don't think it is needed.
>>>>>>> 4. There is another case you didn't list where the EMF can be there
>> but
>>>>>> no
>>>>>>> EM and enhancement should happen ASAP: deserialization ;)
>>>>>>> 5. Finally there is a subtle difference between SE and EE case where
>>>> one
>>>>>>> will trigger the agent and the other will just add the transformer in
>>>> the
>>>>>>> classloader through PersistenUnitInfo (and container should handle
>> this
>>>>>>> additional properly), I don't know if our agent should be compatible
>>>> with
>>>>>>> it for apploader (jvm one).
>>>>>>> 
>>>>>>> Romain Manni-Bucau
>>>>>>> @rmannibucau <https://twitter.com/rmannibucau> |  Blog
>>>>>>> <https://rmannibucau.metawerx.net/> | Old Blog
>>>>>>> <http://rmannibucau.wordpress.com> | Github <
>>>>>> https://github.com/rmannibucau> |
>>>>>>> LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
>>>>>>> <
>>>>>> 
>>>> 
>> https://www.packtpub.com/application-development/java-ee-8-high-performance
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>> Le ven. 17 juil. 2020 à 09:35, Mark Struberg
>> <struberg@yahoo.de.invalid
>>>>> 
>>>>>> a
>>>>>>> écrit :
>>>>>>> 
>>>>>>>> hi folks!
>>>>>>>> 
>>>>>>>> I'm right now cleaning up old code in our enhancer. Like removing
>>>> java5
>>>>>>>> hacks, etc
>>>>>>>> This is also triggered by our recent discussion about _transform and
>>>>>> other
>>>>>>>> pieces.
>>>>>>>> Slowly getting my head into the right space for it. This is way more
>>>>>>>> complex than I remembered ;)
>>>>>>>> 
>>>>>>>> So here is my next puzzle:
>>>>>>>> 
>>>>>>>> I've created a new example with 2 classes: Person and Employee
>> extends
>>>>>>>> Person
>>>>>>>> Plus a persistence.xml with enlisting those 2 classes (makes a
>>>>>>>> difference!) and essentially
>>>>>>>> <property name="openjpa.DynamicEnhancementAgent" value="true"/>
>>>>>>>> <property name="openjpa.RuntimeUnenhancedClasses"
>> value="supported"/>
>>>>>>>> The reason I switched on RuntimeUnenhancedClasses is that this check
>>>> is
>>>>>>>> performed when the BrokerFactory gets created.
>>>>>>>> And if the classes are not build-time enhanced, then it fails in
>>>>>>>> 
>>>>>> 
>>>> 
>> org.apache.openjpa.enhance.ManagedClassSubclasser#prepareUnenhancedClasses
>>>>>>>> if (conf.getRuntimeUnenhancedClassesConstant() !=
>>>>>>>> RuntimeUnenhancedClassesModes.SUPPORTED) { ..
>>>>>>>> And if you switch to supported, then it will create a new subclass
>> and
>>>>>>>> replaces field access to the getters/setters. Sadly
>>>>>>>> java.lang.instrument.Instrumentation#retransform cannot be used to
>> add
>>>>>> new
>>>>>>>> fields or methods. Otherwise we could do a direct full replacement
>> of
>>>>>> this
>>>>>>>> class.
>>>>>>>> 
>>>>>>>> Fun thing is that later on in
>>>>>>>> 
>>>>>> 
>>>> 
>> org.apache.openjpa.persistence.PersistenceProviderImpl#createEntityManagerFactory(java.lang.String,
>>>>>>>> java.lang.String, java.util.Map)
>>>>>>>> we call loadAgent(factory);
>>>>>>>> But what is it supposed to do? Which cases does it serve?
>>>>>>>> If the classes did not have been already enhanced at build time nor
>>>> via
>>>>>>>> javaagent they will now be subclassed by ManagedClassSubclasser.
>>>>>>>> And if we do not set RuntimeUnenhancedClasses=supported then we will
>>>>>> never
>>>>>>>> make it so far but blow up way earlier.
>>>>>>>> 
>>>>>>>> Also: it is nice to have that agent attached. But why? All the
>> entity
>>>>>>>> classe already have been loaded already during BrokerFactory
>> startup.
>>>>>> There
>>>>>>>> is no more entity class left over which needs enhancement, isn't?
>>>>>>>> 
>>>>>>>> This is the log I get which reflects what I mean. Happy to share the
>>>>>> code
>>>>>>>> in a playground branch.
>>>>>>>> 
>>>>>>>> 1261  test-classtransform  INFO   [main] openjpa.Enhance - Creating
>>>>>>>> subclass and redefining methods for "[class
>>>>>>>> org.apache.openjpa.examples.dynenhance.Employee, class
>>>>>>>> org.apache.openjpa.examples.dynenhance.Person]". This means that
>> your
>>>>>>>> application will be less efficient than it would if you ran the
>>>> OpenJPA
>>>>>>>> enhancer.
>>>>>>>> 1412  test-classtransform  INFO   [main] openjpa.Runtime - OpenJPA
>>>>>>>> dynamically loaded the class enhancer. Any classes that were not
>>>>>> enhanced
>>>>>>>> at build time will be enhanced when they are loaded by the JVM.
>>>>>>>> 
>>>>>>>> 
>>>>>>>> LieGrue,
>>>>>>>> strub
>> 
>> 


Re: A few runtime enhancement/bytecode questions

Posted by Romain Manni-Bucau <rm...@gmail.com>.
Not sure I got the question but I suspect the case can be reproduced with a
plain new MyEntity() before your Persistence.createEMF.

Romain Manni-Bucau
@rmannibucau <https://twitter.com/rmannibucau> |  Blog
<https://rmannibucau.metawerx.net/> | Old Blog
<http://rmannibucau.wordpress.com> | Github <https://github.com/rmannibucau> |
LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
<https://www.packtpub.com/application-development/java-ee-8-high-performance>


Le sam. 18 juil. 2020 à 17:57, Mark Struberg <st...@yahoo.de.invalid> a
écrit :

> Found it yesterday when reviewing my sample with Romain:
>
> I apparently did copy the following property over from another example:
> <property name="openjpa.InitializeEagerly" value="true"/>
> And this did lead to already trigger the class transformation while
> createEntityManagerFactory.
>
> I did create a few samples, but did not manage to trigger any subsequent
> classloading at all. So no wonder in which case this could hit us yet.
> Before we introduce another expensive mechanism I would love to understand
> when the situation occurs at all.
>
> LieGrue,
> strub
>
>
>
>
>
> > Am 17.07.2020 um 12:03 schrieb Romain Manni-Bucau <rmannibucau@gmail.com
> >:
> >
> > Le ven. 17 juil. 2020 à 11:27, Mark Struberg <struberg@yahoo.de.invalid
> <ma...@yahoo.de.invalid>> a
> > écrit :
> >
> >> answers inside.
> >>
> >> LieGrue,
> >> strub
> >>
> >>> Am 17.07.2020 um 11:14 schrieb Romain Manni-Bucau <
> rmannibucau@gmail.com
> >>> :
> >>>
> >>> Le ven. 17 juil. 2020 à 10:45, Mark Struberg <struberg@yahoo.de.invalid
> >
> >> a
> >>> écrit :
> >>>
> >>>> Both prepareUnenhancedClasses and loadAgent already run in
> >>>> createEntityManagerFactory.
> >>>>
> >>>
> >>> Not in general, depends the conf and by default i run in none of both
> >> with
> >>> a standard config for ex for EE.
> >>
> >> Let me rephrase this: both those methods will get called in
> >> createEntityManagerFactory already. If they actually perform some
> bytecode
> >> enhancement is up to configuration and whether the classes have been
> >> enhanced otherwise before ;)
> >>
> >>
> >>>
> >>>
> >>>> crateEntityManager does not trigger enhancement afaict.
> >>>>
> >>>
> >>> createEMF does not since the creation of openjpa is lazy so the first
> >>> createEM does (in general case one again).
> >>
> >> Nope, it really gets called already by createEntityManagerFactory. You
> can
> >> debug into this if you want.
> >>
> >
> > Did and I can guarantee you it is lazy if your conf does not enforce it
> > somehow.
> >
> >
> >>
> >> LieGrue,
> >> strub
> >>
> >>
> >>>
> >>>>
> >>>> LieGrue,
> >>>> strub
> >>>>
> >>>>> Am 17.07.2020 um 10:11 schrieb Romain Manni-Bucau <
> >> rmannibucau@gmail.com
> >>>>> :
> >>>>>
> >>>>> Hi Mark,
> >>>>>
> >>>>> If it helps:
> >>>>>
> >>>>> 1.
> org.apache.openjpa.kernel.AbstractBrokerFactory#postCreationCallback
> >>>>> only triggers the prepareUnenhancedClasses if preload=true (never the
> >>>> case
> >>>>> right? ;))
> >>>>> 2. Normally classes are loaded in
> >>>>> there
> org.apache.openjpa.kernel.AbstractBrokerFactory#initializeBroker
> >>>>> *when creating an em, not an emf* so better to have loaded ran the
> >>>>> enhancement early (loadAgent)
> >>>>> 3. Not sure it is done but it can happen 2 has a custom MDR not
> >> returning
> >>>>> right the classes - seems code is ok with that. I don't know if it
> is a
> >>>>> case we want to handle, I don't think it is needed.
> >>>>> 4. There is another case you didn't list where the EMF can be there
> but
> >>>> no
> >>>>> EM and enhancement should happen ASAP: deserialization ;)
> >>>>> 5. Finally there is a subtle difference between SE and EE case where
> >> one
> >>>>> will trigger the agent and the other will just add the transformer in
> >> the
> >>>>> classloader through PersistenUnitInfo (and container should handle
> this
> >>>>> additional properly), I don't know if our agent should be compatible
> >> with
> >>>>> it for apploader (jvm one).
> >>>>>
> >>>>> Romain Manni-Bucau
> >>>>> @rmannibucau <https://twitter.com/rmannibucau> |  Blog
> >>>>> <https://rmannibucau.metawerx.net/> | Old Blog
> >>>>> <http://rmannibucau.wordpress.com> | Github <
> >>>> https://github.com/rmannibucau> |
> >>>>> LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
> >>>>> <
> >>>>
> >>
> https://www.packtpub.com/application-development/java-ee-8-high-performance
> >>>>>
> >>>>>
> >>>>>
> >>>>> Le ven. 17 juil. 2020 à 09:35, Mark Struberg
> <struberg@yahoo.de.invalid
> >>>
> >>>> a
> >>>>> écrit :
> >>>>>
> >>>>>> hi folks!
> >>>>>>
> >>>>>> I'm right now cleaning up old code in our enhancer. Like removing
> >> java5
> >>>>>> hacks, etc
> >>>>>> This is also triggered by our recent discussion about _transform and
> >>>> other
> >>>>>> pieces.
> >>>>>> Slowly getting my head into the right space for it. This is way more
> >>>>>> complex than I remembered ;)
> >>>>>>
> >>>>>> So here is my next puzzle:
> >>>>>>
> >>>>>> I've created a new example with 2 classes: Person and Employee
> extends
> >>>>>> Person
> >>>>>> Plus a persistence.xml with enlisting those 2 classes (makes a
> >>>>>> difference!) and essentially
> >>>>>> <property name="openjpa.DynamicEnhancementAgent" value="true"/>
> >>>>>> <property name="openjpa.RuntimeUnenhancedClasses"
> value="supported"/>
> >>>>>> The reason I switched on RuntimeUnenhancedClasses is that this check
> >> is
> >>>>>> performed when the BrokerFactory gets created.
> >>>>>> And if the classes are not build-time enhanced, then it fails in
> >>>>>>
> >>>>
> >>
> org.apache.openjpa.enhance.ManagedClassSubclasser#prepareUnenhancedClasses
> >>>>>> if (conf.getRuntimeUnenhancedClassesConstant() !=
> >>>>>> RuntimeUnenhancedClassesModes.SUPPORTED) { ..
> >>>>>> And if you switch to supported, then it will create a new subclass
> and
> >>>>>> replaces field access to the getters/setters. Sadly
> >>>>>> java.lang.instrument.Instrumentation#retransform cannot be used to
> add
> >>>> new
> >>>>>> fields or methods. Otherwise we could do a direct full replacement
> of
> >>>> this
> >>>>>> class.
> >>>>>>
> >>>>>> Fun thing is that later on in
> >>>>>>
> >>>>
> >>
> org.apache.openjpa.persistence.PersistenceProviderImpl#createEntityManagerFactory(java.lang.String,
> >>>>>> java.lang.String, java.util.Map)
> >>>>>> we call loadAgent(factory);
> >>>>>> But what is it supposed to do? Which cases does it serve?
> >>>>>> If the classes did not have been already enhanced at build time nor
> >> via
> >>>>>> javaagent they will now be subclassed by ManagedClassSubclasser.
> >>>>>> And if we do not set RuntimeUnenhancedClasses=supported then we will
> >>>> never
> >>>>>> make it so far but blow up way earlier.
> >>>>>>
> >>>>>> Also: it is nice to have that agent attached. But why? All the
> entity
> >>>>>> classe already have been loaded already during BrokerFactory
> startup.
> >>>> There
> >>>>>> is no more entity class left over which needs enhancement, isn't?
> >>>>>>
> >>>>>> This is the log I get which reflects what I mean. Happy to share the
> >>>> code
> >>>>>> in a playground branch.
> >>>>>>
> >>>>>> 1261  test-classtransform  INFO   [main] openjpa.Enhance - Creating
> >>>>>> subclass and redefining methods for "[class
> >>>>>> org.apache.openjpa.examples.dynenhance.Employee, class
> >>>>>> org.apache.openjpa.examples.dynenhance.Person]". This means that
> your
> >>>>>> application will be less efficient than it would if you ran the
> >> OpenJPA
> >>>>>> enhancer.
> >>>>>> 1412  test-classtransform  INFO   [main] openjpa.Runtime - OpenJPA
> >>>>>> dynamically loaded the class enhancer. Any classes that were not
> >>>> enhanced
> >>>>>> at build time will be enhanced when they are loaded by the JVM.
> >>>>>>
> >>>>>>
> >>>>>> LieGrue,
> >>>>>> strub
>
>

Re: A few runtime enhancement/bytecode questions

Posted by Mark Struberg <st...@yahoo.de.INVALID>.
Found it yesterday when reviewing my sample with Romain:

I apparently did copy the following property over from another example:
<property name="openjpa.InitializeEagerly" value="true"/>
And this did lead to already trigger the class transformation while createEntityManagerFactory.

I did create a few samples, but did not manage to trigger any subsequent classloading at all. So no wonder in which case this could hit us yet.
Before we introduce another expensive mechanism I would love to understand when the situation occurs at all.

LieGrue,
strub





> Am 17.07.2020 um 12:03 schrieb Romain Manni-Bucau <rm...@gmail.com>:
> 
> Le ven. 17 juil. 2020 à 11:27, Mark Struberg <struberg@yahoo.de.invalid <ma...@yahoo.de.invalid>> a
> écrit :
> 
>> answers inside.
>> 
>> LieGrue,
>> strub
>> 
>>> Am 17.07.2020 um 11:14 schrieb Romain Manni-Bucau <rmannibucau@gmail.com
>>> :
>>> 
>>> Le ven. 17 juil. 2020 à 10:45, Mark Struberg <st...@yahoo.de.invalid>
>> a
>>> écrit :
>>> 
>>>> Both prepareUnenhancedClasses and loadAgent already run in
>>>> createEntityManagerFactory.
>>>> 
>>> 
>>> Not in general, depends the conf and by default i run in none of both
>> with
>>> a standard config for ex for EE.
>> 
>> Let me rephrase this: both those methods will get called in
>> createEntityManagerFactory already. If they actually perform some bytecode
>> enhancement is up to configuration and whether the classes have been
>> enhanced otherwise before ;)
>> 
>> 
>>> 
>>> 
>>>> crateEntityManager does not trigger enhancement afaict.
>>>> 
>>> 
>>> createEMF does not since the creation of openjpa is lazy so the first
>>> createEM does (in general case one again).
>> 
>> Nope, it really gets called already by createEntityManagerFactory. You can
>> debug into this if you want.
>> 
> 
> Did and I can guarantee you it is lazy if your conf does not enforce it
> somehow.
> 
> 
>> 
>> LieGrue,
>> strub
>> 
>> 
>>> 
>>>> 
>>>> LieGrue,
>>>> strub
>>>> 
>>>>> Am 17.07.2020 um 10:11 schrieb Romain Manni-Bucau <
>> rmannibucau@gmail.com
>>>>> :
>>>>> 
>>>>> Hi Mark,
>>>>> 
>>>>> If it helps:
>>>>> 
>>>>> 1. org.apache.openjpa.kernel.AbstractBrokerFactory#postCreationCallback
>>>>> only triggers the prepareUnenhancedClasses if preload=true (never the
>>>> case
>>>>> right? ;))
>>>>> 2. Normally classes are loaded in
>>>>> there org.apache.openjpa.kernel.AbstractBrokerFactory#initializeBroker
>>>>> *when creating an em, not an emf* so better to have loaded ran the
>>>>> enhancement early (loadAgent)
>>>>> 3. Not sure it is done but it can happen 2 has a custom MDR not
>> returning
>>>>> right the classes - seems code is ok with that. I don't know if it is a
>>>>> case we want to handle, I don't think it is needed.
>>>>> 4. There is another case you didn't list where the EMF can be there but
>>>> no
>>>>> EM and enhancement should happen ASAP: deserialization ;)
>>>>> 5. Finally there is a subtle difference between SE and EE case where
>> one
>>>>> will trigger the agent and the other will just add the transformer in
>> the
>>>>> classloader through PersistenUnitInfo (and container should handle this
>>>>> additional properly), I don't know if our agent should be compatible
>> with
>>>>> it for apploader (jvm one).
>>>>> 
>>>>> Romain Manni-Bucau
>>>>> @rmannibucau <https://twitter.com/rmannibucau> |  Blog
>>>>> <https://rmannibucau.metawerx.net/> | Old Blog
>>>>> <http://rmannibucau.wordpress.com> | Github <
>>>> https://github.com/rmannibucau> |
>>>>> LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
>>>>> <
>>>> 
>> https://www.packtpub.com/application-development/java-ee-8-high-performance
>>>>> 
>>>>> 
>>>>> 
>>>>> Le ven. 17 juil. 2020 à 09:35, Mark Struberg <struberg@yahoo.de.invalid
>>> 
>>>> a
>>>>> écrit :
>>>>> 
>>>>>> hi folks!
>>>>>> 
>>>>>> I'm right now cleaning up old code in our enhancer. Like removing
>> java5
>>>>>> hacks, etc
>>>>>> This is also triggered by our recent discussion about _transform and
>>>> other
>>>>>> pieces.
>>>>>> Slowly getting my head into the right space for it. This is way more
>>>>>> complex than I remembered ;)
>>>>>> 
>>>>>> So here is my next puzzle:
>>>>>> 
>>>>>> I've created a new example with 2 classes: Person and Employee extends
>>>>>> Person
>>>>>> Plus a persistence.xml with enlisting those 2 classes (makes a
>>>>>> difference!) and essentially
>>>>>> <property name="openjpa.DynamicEnhancementAgent" value="true"/>
>>>>>> <property name="openjpa.RuntimeUnenhancedClasses" value="supported"/>
>>>>>> The reason I switched on RuntimeUnenhancedClasses is that this check
>> is
>>>>>> performed when the BrokerFactory gets created.
>>>>>> And if the classes are not build-time enhanced, then it fails in
>>>>>> 
>>>> 
>> org.apache.openjpa.enhance.ManagedClassSubclasser#prepareUnenhancedClasses
>>>>>> if (conf.getRuntimeUnenhancedClassesConstant() !=
>>>>>> RuntimeUnenhancedClassesModes.SUPPORTED) { ..
>>>>>> And if you switch to supported, then it will create a new subclass and
>>>>>> replaces field access to the getters/setters. Sadly
>>>>>> java.lang.instrument.Instrumentation#retransform cannot be used to add
>>>> new
>>>>>> fields or methods. Otherwise we could do a direct full replacement of
>>>> this
>>>>>> class.
>>>>>> 
>>>>>> Fun thing is that later on in
>>>>>> 
>>>> 
>> org.apache.openjpa.persistence.PersistenceProviderImpl#createEntityManagerFactory(java.lang.String,
>>>>>> java.lang.String, java.util.Map)
>>>>>> we call loadAgent(factory);
>>>>>> But what is it supposed to do? Which cases does it serve?
>>>>>> If the classes did not have been already enhanced at build time nor
>> via
>>>>>> javaagent they will now be subclassed by ManagedClassSubclasser.
>>>>>> And if we do not set RuntimeUnenhancedClasses=supported then we will
>>>> never
>>>>>> make it so far but blow up way earlier.
>>>>>> 
>>>>>> Also: it is nice to have that agent attached. But why? All the entity
>>>>>> classe already have been loaded already during BrokerFactory startup.
>>>> There
>>>>>> is no more entity class left over which needs enhancement, isn't?
>>>>>> 
>>>>>> This is the log I get which reflects what I mean. Happy to share the
>>>> code
>>>>>> in a playground branch.
>>>>>> 
>>>>>> 1261  test-classtransform  INFO   [main] openjpa.Enhance - Creating
>>>>>> subclass and redefining methods for "[class
>>>>>> org.apache.openjpa.examples.dynenhance.Employee, class
>>>>>> org.apache.openjpa.examples.dynenhance.Person]". This means that your
>>>>>> application will be less efficient than it would if you ran the
>> OpenJPA
>>>>>> enhancer.
>>>>>> 1412  test-classtransform  INFO   [main] openjpa.Runtime - OpenJPA
>>>>>> dynamically loaded the class enhancer. Any classes that were not
>>>> enhanced
>>>>>> at build time will be enhanced when they are loaded by the JVM.
>>>>>> 
>>>>>> 
>>>>>> LieGrue,
>>>>>> strub


Re: A few runtime enhancement/bytecode questions

Posted by Romain Manni-Bucau <rm...@gmail.com>.
Le ven. 17 juil. 2020 à 11:27, Mark Struberg <st...@yahoo.de.invalid> a
écrit :

> answers inside.
>
> LieGrue,
> strub
>
> > Am 17.07.2020 um 11:14 schrieb Romain Manni-Bucau <rmannibucau@gmail.com
> >:
> >
> > Le ven. 17 juil. 2020 à 10:45, Mark Struberg <st...@yahoo.de.invalid>
> a
> > écrit :
> >
> >> Both prepareUnenhancedClasses and loadAgent already run in
> >> createEntityManagerFactory.
> >>
> >
> > Not in general, depends the conf and by default i run in none of both
> with
> > a standard config for ex for EE.
>
> Let me rephrase this: both those methods will get called in
> createEntityManagerFactory already. If they actually perform some bytecode
> enhancement is up to configuration and whether the classes have been
> enhanced otherwise before ;)
>
>
> >
> >
> >> crateEntityManager does not trigger enhancement afaict.
> >>
> >
> > createEMF does not since the creation of openjpa is lazy so the first
> > createEM does (in general case one again).
>
> Nope, it really gets called already by createEntityManagerFactory. You can
> debug into this if you want.
>

Did and I can guarantee you it is lazy if your conf does not enforce it
somehow.


>
> LieGrue,
> strub
>
>
> >
> >>
> >> LieGrue,
> >> strub
> >>
> >>> Am 17.07.2020 um 10:11 schrieb Romain Manni-Bucau <
> rmannibucau@gmail.com
> >>> :
> >>>
> >>> Hi Mark,
> >>>
> >>> If it helps:
> >>>
> >>> 1. org.apache.openjpa.kernel.AbstractBrokerFactory#postCreationCallback
> >>> only triggers the prepareUnenhancedClasses if preload=true (never the
> >> case
> >>> right? ;))
> >>> 2. Normally classes are loaded in
> >>> there org.apache.openjpa.kernel.AbstractBrokerFactory#initializeBroker
> >>> *when creating an em, not an emf* so better to have loaded ran the
> >>> enhancement early (loadAgent)
> >>> 3. Not sure it is done but it can happen 2 has a custom MDR not
> returning
> >>> right the classes - seems code is ok with that. I don't know if it is a
> >>> case we want to handle, I don't think it is needed.
> >>> 4. There is another case you didn't list where the EMF can be there but
> >> no
> >>> EM and enhancement should happen ASAP: deserialization ;)
> >>> 5. Finally there is a subtle difference between SE and EE case where
> one
> >>> will trigger the agent and the other will just add the transformer in
> the
> >>> classloader through PersistenUnitInfo (and container should handle this
> >>> additional properly), I don't know if our agent should be compatible
> with
> >>> it for apploader (jvm one).
> >>>
> >>> Romain Manni-Bucau
> >>> @rmannibucau <https://twitter.com/rmannibucau> |  Blog
> >>> <https://rmannibucau.metawerx.net/> | Old Blog
> >>> <http://rmannibucau.wordpress.com> | Github <
> >> https://github.com/rmannibucau> |
> >>> LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
> >>> <
> >>
> https://www.packtpub.com/application-development/java-ee-8-high-performance
> >>>
> >>>
> >>>
> >>> Le ven. 17 juil. 2020 à 09:35, Mark Struberg <struberg@yahoo.de.invalid
> >
> >> a
> >>> écrit :
> >>>
> >>>> hi folks!
> >>>>
> >>>> I'm right now cleaning up old code in our enhancer. Like removing
> java5
> >>>> hacks, etc
> >>>> This is also triggered by our recent discussion about _transform and
> >> other
> >>>> pieces.
> >>>> Slowly getting my head into the right space for it. This is way more
> >>>> complex than I remembered ;)
> >>>>
> >>>> So here is my next puzzle:
> >>>>
> >>>> I've created a new example with 2 classes: Person and Employee extends
> >>>> Person
> >>>> Plus a persistence.xml with enlisting those 2 classes (makes a
> >>>> difference!) and essentially
> >>>> <property name="openjpa.DynamicEnhancementAgent" value="true"/>
> >>>> <property name="openjpa.RuntimeUnenhancedClasses" value="supported"/>
> >>>> The reason I switched on RuntimeUnenhancedClasses is that this check
> is
> >>>> performed when the BrokerFactory gets created.
> >>>> And if the classes are not build-time enhanced, then it fails in
> >>>>
> >>
> org.apache.openjpa.enhance.ManagedClassSubclasser#prepareUnenhancedClasses
> >>>> if (conf.getRuntimeUnenhancedClassesConstant() !=
> >>>> RuntimeUnenhancedClassesModes.SUPPORTED) { ..
> >>>> And if you switch to supported, then it will create a new subclass and
> >>>> replaces field access to the getters/setters. Sadly
> >>>> java.lang.instrument.Instrumentation#retransform cannot be used to add
> >> new
> >>>> fields or methods. Otherwise we could do a direct full replacement of
> >> this
> >>>> class.
> >>>>
> >>>> Fun thing is that later on in
> >>>>
> >>
> org.apache.openjpa.persistence.PersistenceProviderImpl#createEntityManagerFactory(java.lang.String,
> >>>> java.lang.String, java.util.Map)
> >>>> we call loadAgent(factory);
> >>>> But what is it supposed to do? Which cases does it serve?
> >>>> If the classes did not have been already enhanced at build time nor
> via
> >>>> javaagent they will now be subclassed by ManagedClassSubclasser.
> >>>> And if we do not set RuntimeUnenhancedClasses=supported then we will
> >> never
> >>>> make it so far but blow up way earlier.
> >>>>
> >>>> Also: it is nice to have that agent attached. But why? All the entity
> >>>> classe already have been loaded already during BrokerFactory startup.
> >> There
> >>>> is no more entity class left over which needs enhancement, isn't?
> >>>>
> >>>> This is the log I get which reflects what I mean. Happy to share the
> >> code
> >>>> in a playground branch.
> >>>>
> >>>> 1261  test-classtransform  INFO   [main] openjpa.Enhance - Creating
> >>>> subclass and redefining methods for "[class
> >>>> org.apache.openjpa.examples.dynenhance.Employee, class
> >>>> org.apache.openjpa.examples.dynenhance.Person]". This means that your
> >>>> application will be less efficient than it would if you ran the
> OpenJPA
> >>>> enhancer.
> >>>> 1412  test-classtransform  INFO   [main] openjpa.Runtime - OpenJPA
> >>>> dynamically loaded the class enhancer. Any classes that were not
> >> enhanced
> >>>> at build time will be enhanced when they are loaded by the JVM.
> >>>>
> >>>>
> >>>> LieGrue,
> >>>> strub
> >>>>
> >>>>
> >>
> >>
>
>

Re: A few runtime enhancement/bytecode questions

Posted by Mark Struberg <st...@yahoo.de.INVALID>.
answers inside.

LieGrue,
strub

> Am 17.07.2020 um 11:14 schrieb Romain Manni-Bucau <rm...@gmail.com>:
> 
> Le ven. 17 juil. 2020 à 10:45, Mark Struberg <st...@yahoo.de.invalid> a
> écrit :
> 
>> Both prepareUnenhancedClasses and loadAgent already run in
>> createEntityManagerFactory.
>> 
> 
> Not in general, depends the conf and by default i run in none of both with
> a standard config for ex for EE.

Let me rephrase this: both those methods will get called in createEntityManagerFactory already. If they actually perform some bytecode enhancement is up to configuration and whether the classes have been enhanced otherwise before ;)


> 
> 
>> crateEntityManager does not trigger enhancement afaict.
>> 
> 
> createEMF does not since the creation of openjpa is lazy so the first
> createEM does (in general case one again).

Nope, it really gets called already by createEntityManagerFactory. You can debug into this if you want.

LieGrue,
strub


> 
>> 
>> LieGrue,
>> strub
>> 
>>> Am 17.07.2020 um 10:11 schrieb Romain Manni-Bucau <rmannibucau@gmail.com
>>> :
>>> 
>>> Hi Mark,
>>> 
>>> If it helps:
>>> 
>>> 1. org.apache.openjpa.kernel.AbstractBrokerFactory#postCreationCallback
>>> only triggers the prepareUnenhancedClasses if preload=true (never the
>> case
>>> right? ;))
>>> 2. Normally classes are loaded in
>>> there org.apache.openjpa.kernel.AbstractBrokerFactory#initializeBroker
>>> *when creating an em, not an emf* so better to have loaded ran the
>>> enhancement early (loadAgent)
>>> 3. Not sure it is done but it can happen 2 has a custom MDR not returning
>>> right the classes - seems code is ok with that. I don't know if it is a
>>> case we want to handle, I don't think it is needed.
>>> 4. There is another case you didn't list where the EMF can be there but
>> no
>>> EM and enhancement should happen ASAP: deserialization ;)
>>> 5. Finally there is a subtle difference between SE and EE case where one
>>> will trigger the agent and the other will just add the transformer in the
>>> classloader through PersistenUnitInfo (and container should handle this
>>> additional properly), I don't know if our agent should be compatible with
>>> it for apploader (jvm one).
>>> 
>>> Romain Manni-Bucau
>>> @rmannibucau <https://twitter.com/rmannibucau> |  Blog
>>> <https://rmannibucau.metawerx.net/> | Old Blog
>>> <http://rmannibucau.wordpress.com> | Github <
>> https://github.com/rmannibucau> |
>>> LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
>>> <
>> https://www.packtpub.com/application-development/java-ee-8-high-performance
>>> 
>>> 
>>> 
>>> Le ven. 17 juil. 2020 à 09:35, Mark Struberg <st...@yahoo.de.invalid>
>> a
>>> écrit :
>>> 
>>>> hi folks!
>>>> 
>>>> I'm right now cleaning up old code in our enhancer. Like removing java5
>>>> hacks, etc
>>>> This is also triggered by our recent discussion about _transform and
>> other
>>>> pieces.
>>>> Slowly getting my head into the right space for it. This is way more
>>>> complex than I remembered ;)
>>>> 
>>>> So here is my next puzzle:
>>>> 
>>>> I've created a new example with 2 classes: Person and Employee extends
>>>> Person
>>>> Plus a persistence.xml with enlisting those 2 classes (makes a
>>>> difference!) and essentially
>>>> <property name="openjpa.DynamicEnhancementAgent" value="true"/>
>>>> <property name="openjpa.RuntimeUnenhancedClasses" value="supported"/>
>>>> The reason I switched on RuntimeUnenhancedClasses is that this check is
>>>> performed when the BrokerFactory gets created.
>>>> And if the classes are not build-time enhanced, then it fails in
>>>> 
>> org.apache.openjpa.enhance.ManagedClassSubclasser#prepareUnenhancedClasses
>>>> if (conf.getRuntimeUnenhancedClassesConstant() !=
>>>> RuntimeUnenhancedClassesModes.SUPPORTED) { ..
>>>> And if you switch to supported, then it will create a new subclass and
>>>> replaces field access to the getters/setters. Sadly
>>>> java.lang.instrument.Instrumentation#retransform cannot be used to add
>> new
>>>> fields or methods. Otherwise we could do a direct full replacement of
>> this
>>>> class.
>>>> 
>>>> Fun thing is that later on in
>>>> 
>> org.apache.openjpa.persistence.PersistenceProviderImpl#createEntityManagerFactory(java.lang.String,
>>>> java.lang.String, java.util.Map)
>>>> we call loadAgent(factory);
>>>> But what is it supposed to do? Which cases does it serve?
>>>> If the classes did not have been already enhanced at build time nor via
>>>> javaagent they will now be subclassed by ManagedClassSubclasser.
>>>> And if we do not set RuntimeUnenhancedClasses=supported then we will
>> never
>>>> make it so far but blow up way earlier.
>>>> 
>>>> Also: it is nice to have that agent attached. But why? All the entity
>>>> classe already have been loaded already during BrokerFactory startup.
>> There
>>>> is no more entity class left over which needs enhancement, isn't?
>>>> 
>>>> This is the log I get which reflects what I mean. Happy to share the
>> code
>>>> in a playground branch.
>>>> 
>>>> 1261  test-classtransform  INFO   [main] openjpa.Enhance - Creating
>>>> subclass and redefining methods for "[class
>>>> org.apache.openjpa.examples.dynenhance.Employee, class
>>>> org.apache.openjpa.examples.dynenhance.Person]". This means that your
>>>> application will be less efficient than it would if you ran the OpenJPA
>>>> enhancer.
>>>> 1412  test-classtransform  INFO   [main] openjpa.Runtime - OpenJPA
>>>> dynamically loaded the class enhancer. Any classes that were not
>> enhanced
>>>> at build time will be enhanced when they are loaded by the JVM.
>>>> 
>>>> 
>>>> LieGrue,
>>>> strub
>>>> 
>>>> 
>> 
>> 


Re: A few runtime enhancement/bytecode questions

Posted by Romain Manni-Bucau <rm...@gmail.com>.
Le ven. 17 juil. 2020 à 10:45, Mark Struberg <st...@yahoo.de.invalid> a
écrit :

> Both prepareUnenhancedClasses and loadAgent already run in
> createEntityManagerFactory.
>

Not in general, depends the conf and by default i run in none of both with
a standard config for ex for EE.


> crateEntityManager does not trigger enhancement afaict.
>

createEMF does not since the creation of openjpa is lazy so the first
createEM does (in general case one again).


>
> LieGrue,
> strub
>
> > Am 17.07.2020 um 10:11 schrieb Romain Manni-Bucau <rmannibucau@gmail.com
> >:
> >
> > Hi Mark,
> >
> > If it helps:
> >
> > 1. org.apache.openjpa.kernel.AbstractBrokerFactory#postCreationCallback
> > only triggers the prepareUnenhancedClasses if preload=true (never the
> case
> > right? ;))
> > 2. Normally classes are loaded in
> > there org.apache.openjpa.kernel.AbstractBrokerFactory#initializeBroker
> > *when creating an em, not an emf* so better to have loaded ran the
> > enhancement early (loadAgent)
> > 3. Not sure it is done but it can happen 2 has a custom MDR not returning
> > right the classes - seems code is ok with that. I don't know if it is a
> > case we want to handle, I don't think it is needed.
> > 4. There is another case you didn't list where the EMF can be there but
> no
> > EM and enhancement should happen ASAP: deserialization ;)
> > 5. Finally there is a subtle difference between SE and EE case where one
> > will trigger the agent and the other will just add the transformer in the
> > classloader through PersistenUnitInfo (and container should handle this
> > additional properly), I don't know if our agent should be compatible with
> > it for apploader (jvm one).
> >
> > Romain Manni-Bucau
> > @rmannibucau <https://twitter.com/rmannibucau> |  Blog
> > <https://rmannibucau.metawerx.net/> | Old Blog
> > <http://rmannibucau.wordpress.com> | Github <
> https://github.com/rmannibucau> |
> > LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
> > <
> https://www.packtpub.com/application-development/java-ee-8-high-performance
> >
> >
> >
> > Le ven. 17 juil. 2020 à 09:35, Mark Struberg <st...@yahoo.de.invalid>
> a
> > écrit :
> >
> >> hi folks!
> >>
> >> I'm right now cleaning up old code in our enhancer. Like removing java5
> >> hacks, etc
> >> This is also triggered by our recent discussion about _transform and
> other
> >> pieces.
> >> Slowly getting my head into the right space for it. This is way more
> >> complex than I remembered ;)
> >>
> >> So here is my next puzzle:
> >>
> >> I've created a new example with 2 classes: Person and Employee extends
> >> Person
> >> Plus a persistence.xml with enlisting those 2 classes (makes a
> >> difference!) and essentially
> >> <property name="openjpa.DynamicEnhancementAgent" value="true"/>
> >> <property name="openjpa.RuntimeUnenhancedClasses" value="supported"/>
> >> The reason I switched on RuntimeUnenhancedClasses is that this check is
> >> performed when the BrokerFactory gets created.
> >> And if the classes are not build-time enhanced, then it fails in
> >>
> org.apache.openjpa.enhance.ManagedClassSubclasser#prepareUnenhancedClasses
> >> if (conf.getRuntimeUnenhancedClassesConstant() !=
> >> RuntimeUnenhancedClassesModes.SUPPORTED) { ..
> >> And if you switch to supported, then it will create a new subclass and
> >> replaces field access to the getters/setters. Sadly
> >> java.lang.instrument.Instrumentation#retransform cannot be used to add
> new
> >> fields or methods. Otherwise we could do a direct full replacement of
> this
> >> class.
> >>
> >> Fun thing is that later on in
> >>
> org.apache.openjpa.persistence.PersistenceProviderImpl#createEntityManagerFactory(java.lang.String,
> >> java.lang.String, java.util.Map)
> >> we call loadAgent(factory);
> >> But what is it supposed to do? Which cases does it serve?
> >> If the classes did not have been already enhanced at build time nor via
> >> javaagent they will now be subclassed by ManagedClassSubclasser.
> >> And if we do not set RuntimeUnenhancedClasses=supported then we will
> never
> >> make it so far but blow up way earlier.
> >>
> >> Also: it is nice to have that agent attached. But why? All the entity
> >> classe already have been loaded already during BrokerFactory startup.
> There
> >> is no more entity class left over which needs enhancement, isn't?
> >>
> >> This is the log I get which reflects what I mean. Happy to share the
> code
> >> in a playground branch.
> >>
> >> 1261  test-classtransform  INFO   [main] openjpa.Enhance - Creating
> >> subclass and redefining methods for "[class
> >> org.apache.openjpa.examples.dynenhance.Employee, class
> >> org.apache.openjpa.examples.dynenhance.Person]". This means that your
> >> application will be less efficient than it would if you ran the OpenJPA
> >> enhancer.
> >> 1412  test-classtransform  INFO   [main] openjpa.Runtime - OpenJPA
> >> dynamically loaded the class enhancer. Any classes that were not
> enhanced
> >> at build time will be enhanced when they are loaded by the JVM.
> >>
> >>
> >> LieGrue,
> >> strub
> >>
> >>
>
>

Re: A few runtime enhancement/bytecode questions

Posted by Mark Struberg <st...@yahoo.de.INVALID>.
Both prepareUnenhancedClasses and loadAgent already run in createEntityManagerFactory.
crateEntityManager does not trigger enhancement afaict.

LieGrue,
strub

> Am 17.07.2020 um 10:11 schrieb Romain Manni-Bucau <rm...@gmail.com>:
> 
> Hi Mark,
> 
> If it helps:
> 
> 1. org.apache.openjpa.kernel.AbstractBrokerFactory#postCreationCallback
> only triggers the prepareUnenhancedClasses if preload=true (never the case
> right? ;))
> 2. Normally classes are loaded in
> there org.apache.openjpa.kernel.AbstractBrokerFactory#initializeBroker
> *when creating an em, not an emf* so better to have loaded ran the
> enhancement early (loadAgent)
> 3. Not sure it is done but it can happen 2 has a custom MDR not returning
> right the classes - seems code is ok with that. I don't know if it is a
> case we want to handle, I don't think it is needed.
> 4. There is another case you didn't list where the EMF can be there but no
> EM and enhancement should happen ASAP: deserialization ;)
> 5. Finally there is a subtle difference between SE and EE case where one
> will trigger the agent and the other will just add the transformer in the
> classloader through PersistenUnitInfo (and container should handle this
> additional properly), I don't know if our agent should be compatible with
> it for apploader (jvm one).
> 
> Romain Manni-Bucau
> @rmannibucau <https://twitter.com/rmannibucau> |  Blog
> <https://rmannibucau.metawerx.net/> | Old Blog
> <http://rmannibucau.wordpress.com> | Github <https://github.com/rmannibucau> |
> LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
> <https://www.packtpub.com/application-development/java-ee-8-high-performance>
> 
> 
> Le ven. 17 juil. 2020 à 09:35, Mark Struberg <st...@yahoo.de.invalid> a
> écrit :
> 
>> hi folks!
>> 
>> I'm right now cleaning up old code in our enhancer. Like removing java5
>> hacks, etc
>> This is also triggered by our recent discussion about _transform and other
>> pieces.
>> Slowly getting my head into the right space for it. This is way more
>> complex than I remembered ;)
>> 
>> So here is my next puzzle:
>> 
>> I've created a new example with 2 classes: Person and Employee extends
>> Person
>> Plus a persistence.xml with enlisting those 2 classes (makes a
>> difference!) and essentially
>> <property name="openjpa.DynamicEnhancementAgent" value="true"/>
>> <property name="openjpa.RuntimeUnenhancedClasses" value="supported"/>
>> The reason I switched on RuntimeUnenhancedClasses is that this check is
>> performed when the BrokerFactory gets created.
>> And if the classes are not build-time enhanced, then it fails in
>> org.apache.openjpa.enhance.ManagedClassSubclasser#prepareUnenhancedClasses
>> if (conf.getRuntimeUnenhancedClassesConstant() !=
>> RuntimeUnenhancedClassesModes.SUPPORTED) { ..
>> And if you switch to supported, then it will create a new subclass and
>> replaces field access to the getters/setters. Sadly
>> java.lang.instrument.Instrumentation#retransform cannot be used to add new
>> fields or methods. Otherwise we could do a direct full replacement of this
>> class.
>> 
>> Fun thing is that later on in
>> org.apache.openjpa.persistence.PersistenceProviderImpl#createEntityManagerFactory(java.lang.String,
>> java.lang.String, java.util.Map)
>> we call loadAgent(factory);
>> But what is it supposed to do? Which cases does it serve?
>> If the classes did not have been already enhanced at build time nor via
>> javaagent they will now be subclassed by ManagedClassSubclasser.
>> And if we do not set RuntimeUnenhancedClasses=supported then we will never
>> make it so far but blow up way earlier.
>> 
>> Also: it is nice to have that agent attached. But why? All the entity
>> classe already have been loaded already during BrokerFactory startup. There
>> is no more entity class left over which needs enhancement, isn't?
>> 
>> This is the log I get which reflects what I mean. Happy to share the code
>> in a playground branch.
>> 
>> 1261  test-classtransform  INFO   [main] openjpa.Enhance - Creating
>> subclass and redefining methods for "[class
>> org.apache.openjpa.examples.dynenhance.Employee, class
>> org.apache.openjpa.examples.dynenhance.Person]". This means that your
>> application will be less efficient than it would if you ran the OpenJPA
>> enhancer.
>> 1412  test-classtransform  INFO   [main] openjpa.Runtime - OpenJPA
>> dynamically loaded the class enhancer. Any classes that were not enhanced
>> at build time will be enhanced when they are loaded by the JVM.
>> 
>> 
>> LieGrue,
>> strub
>> 
>> 


Re: A few runtime enhancement/bytecode questions

Posted by Romain Manni-Bucau <rm...@gmail.com>.
Hi Mark,

If it helps:

1. org.apache.openjpa.kernel.AbstractBrokerFactory#postCreationCallback
only triggers the prepareUnenhancedClasses if preload=true (never the case
right? ;))
2. Normally classes are loaded in
there org.apache.openjpa.kernel.AbstractBrokerFactory#initializeBroker
*when creating an em, not an emf* so better to have loaded ran the
enhancement early (loadAgent)
3. Not sure it is done but it can happen 2 has a custom MDR not returning
right the classes - seems code is ok with that. I don't know if it is a
case we want to handle, I don't think it is needed.
4. There is another case you didn't list where the EMF can be there but no
EM and enhancement should happen ASAP: deserialization ;)
5. Finally there is a subtle difference between SE and EE case where one
will trigger the agent and the other will just add the transformer in the
classloader through PersistenUnitInfo (and container should handle this
additional properly), I don't know if our agent should be compatible with
it for apploader (jvm one).

Romain Manni-Bucau
@rmannibucau <https://twitter.com/rmannibucau> |  Blog
<https://rmannibucau.metawerx.net/> | Old Blog
<http://rmannibucau.wordpress.com> | Github <https://github.com/rmannibucau> |
LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
<https://www.packtpub.com/application-development/java-ee-8-high-performance>


Le ven. 17 juil. 2020 à 09:35, Mark Struberg <st...@yahoo.de.invalid> a
écrit :

> hi folks!
>
> I'm right now cleaning up old code in our enhancer. Like removing java5
> hacks, etc
> This is also triggered by our recent discussion about _transform and other
> pieces.
> Slowly getting my head into the right space for it. This is way more
> complex than I remembered ;)
>
> So here is my next puzzle:
>
> I've created a new example with 2 classes: Person and Employee extends
> Person
> Plus a persistence.xml with enlisting those 2 classes (makes a
> difference!) and essentially
> <property name="openjpa.DynamicEnhancementAgent" value="true"/>
> <property name="openjpa.RuntimeUnenhancedClasses" value="supported"/>
> The reason I switched on RuntimeUnenhancedClasses is that this check is
> performed when the BrokerFactory gets created.
> And if the classes are not build-time enhanced, then it fails in
> org.apache.openjpa.enhance.ManagedClassSubclasser#prepareUnenhancedClasses
> if (conf.getRuntimeUnenhancedClassesConstant() !=
> RuntimeUnenhancedClassesModes.SUPPORTED) { ..
> And if you switch to supported, then it will create a new subclass and
> replaces field access to the getters/setters. Sadly
> java.lang.instrument.Instrumentation#retransform cannot be used to add new
> fields or methods. Otherwise we could do a direct full replacement of this
> class.
>
> Fun thing is that later on in
> org.apache.openjpa.persistence.PersistenceProviderImpl#createEntityManagerFactory(java.lang.String,
> java.lang.String, java.util.Map)
> we call loadAgent(factory);
> But what is it supposed to do? Which cases does it serve?
> If the classes did not have been already enhanced at build time nor via
> javaagent they will now be subclassed by ManagedClassSubclasser.
> And if we do not set RuntimeUnenhancedClasses=supported then we will never
> make it so far but blow up way earlier.
>
> Also: it is nice to have that agent attached. But why? All the entity
> classe already have been loaded already during BrokerFactory startup. There
> is no more entity class left over which needs enhancement, isn't?
>
> This is the log I get which reflects what I mean. Happy to share the code
> in a playground branch.
>
> 1261  test-classtransform  INFO   [main] openjpa.Enhance - Creating
> subclass and redefining methods for "[class
> org.apache.openjpa.examples.dynenhance.Employee, class
> org.apache.openjpa.examples.dynenhance.Person]". This means that your
> application will be less efficient than it would if you ran the OpenJPA
> enhancer.
> 1412  test-classtransform  INFO   [main] openjpa.Runtime - OpenJPA
> dynamically loaded the class enhancer. Any classes that were not enhanced
> at build time will be enhanced when they are loaded by the JVM.
>
>
> LieGrue,
> strub
>
>