Le dim. 19 juil. 2020 à 00:47, Mark Struberg <strub...@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 <rmannibu...@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 <strub...@yahoo.de.invalid> > a > > écrit : > > > >> no, didn't work. > >> > >> LieGrue, > >> strub > >> > >> > >>> Am 18.07.2020 um 18:00 schrieb Romain Manni-Bucau < > rmannibu...@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 <strub...@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 < > >> rmannibu...@gmail.com > >>>>> : > >>>>> > >>>>> Le ven. 17 juil. 2020 à 11:27, Mark Struberg > <strub...@yahoo.de.invalid > >>>> <mailto:strub...@yahoo.de.invalid>> a > >>>>> écrit : > >>>>> > >>>>>> answers inside. > >>>>>> > >>>>>> LieGrue, > >>>>>> strub > >>>>>> > >>>>>>> Am 17.07.2020 um 11:14 schrieb Romain Manni-Bucau < > >>>> rmannibu...@gmail.com > >>>>>>> : > >>>>>>> > >>>>>>> Le ven. 17 juil. 2020 à 10:45, Mark Struberg > >> <strub...@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 < > >>>>>> rmannibu...@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 > >>>> <strub...@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 > >>>> > >>>> > >> > >> > >