jgrassel commented on pull request #65:
URL: https://github.com/apache/openjpa/pull/65#issuecomment-658350601


   @rmannibucau That optimization sounds like a violation of the 
PersistenceUnitInfo contract:
   ```
   /**
   * Return a new instance of a ClassLoader that the provider may
   * use to temporarily load any classes, resources, or open
   * URLs. The scope and classpath of this loader is exactly the
   * same as that of the loader returned by
   * PersistenceUnitInfo.getClassLoader. None of the classes loaded 
   * by this class loader will be visible to application
   * components. The provider may only use this ClassLoader within 
   * the scope of the createContainerEntityManagerFactory call.
   * @return temporary ClassLoader with same visibility as current 
   * loader
   */
   public ClassLoader getNewTempClassLoader();
   ```
   
   It specifically states `None of the classes loaded by this class loader will 
be visible to application components.` -- that is impossible if the Temporary 
CL is the same object instance as the App CL.
   
   Anyways, the `_transforming` boolean was put in there to catch a reentrant 
call triggered during enhancement, which could only occur if the JPA impl 
classes are loaded by the same CL as the entity classes.  See this flow:
   
   ```
   1.  MyEntity is loaded by the ClassLoader for the first time.  Bytecode is 
fetched, and passed to the enhancer for transformation (if necessary)
   2. Control enters the OpenJPA Enhancer code. (_transforming is set true)
   3. While in the OpenJPA Enhancer code, one of the OpenJPA impl types needs 
to be loaded by the ClassLoader.  This triggers the ClassLoader (which this 
thread has a lock on, as back then CLer access was synchronized) to load that 
OpenJPA impl type's bytecode and calls the enhancer (the CL just knows this is 
a class that it is loading, it cannot distinguish an entity class from a 
non-entity class)
   4. Control re-enters the OpenJPA Enhancer code
   5. Because this reentrancy can only happen if a class is loaded while 
processing the enhancement logic (step 3), the class being requested for 
transformation could only be an openjpa type, which is never going to be 
enhanced.  So return null (no transform) -- this condition is detected by the 
`_transforming` field set in (step 2).
   6. Transformer returns with no change, CLer finishes loading the OpenJPA type
   7. Control returns from the CLer back to the transformer
   8. Transformer finishes transforming the class, and sets _transforming to 
false
   9. Control returns to ClassLoader, which loads the transformed bytecode
   10. Done, profit!
   ```
   
   Now, because ClassLoaders now permit concurrent access among multiple 
threads, that _transforming boolean has to be thread context aware -- it should 
allow any number of threads to use the transformer, but the same thread would 
not be calling a classload and transform for any type other than a JPA provider 
impl type.
   


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


Reply via email to