[ 
https://issues.apache.org/jira/browse/UIMA-5054?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15419558#comment-15419558
 ] 

Marshall Schor edited comment on UIMA-5054 at 8/13/16 7:05 PM:
---------------------------------------------------------------

Even with a null class path, the creation of an extension class loader sets a 
"boundary" for JCas loading.  Inside this boundary, JCas classes are loaded the 
first time (when the process method is called passing a JCas), and even though 
the classes get loaded by the parent classloader (because the extension class 
path loader's classpath is ""), the generators for these classes are associated 
(in a hashmap) with the classloader in effect (that is, the UIMA Extension 
loader).  One possible "fix" for this is to have this process set the generator 
for the parent classloader(s) depending on what the "loading" classloader used 
was.  This sounds like a bug fix we could do in UIMA (assuming it's possible to 
detect the "loading" class loader - not sure if class.getClassloader returns 
the "initiating" or "loading" loader...

After more thought, this isn't the cause or the right fix.  The cause is a bug 
in the design of when JCas classes are loaded.  The design loads these lazily, 
on the first creation of JCas CAS from a CAS, and the load is done one time 
(bug). In this example, the first creation of JCas occurs while in the context 
of class loader #2; JCas class are loaded properly.  However, when we exit that 
context and code loaded under class loader #1 is executed, it also switches 
from the CAS to the JCas (in CustomStatusCallbackListener's 
entityProcessComplete method).  That switch to JCas is the first switch that 
happens while in the context where ClassLoader #1 is in charge. When this 
happens, the JCas classes loadable via that class loader ought to be loaded and 
set up in the generators - this doesn't happen because the logic for JCas 
initialization is buggily to only do it once.

A consequence of this bug would be that had ClassLoader #1 had a definition for 
some UIMA type and ClassLoader #2 had a different definition, because of the 
order in which the swtich to JCas occurs, only the 2nd definition would be 
loaded.  I'll put up another Jira for this.


was (Author: schor):
Even with a null class path, the creation of an extension class loader sets a 
"boundary" for JCas loading.  Inside this boundary, JCas classes are loaded the 
first time (when the process method is called passing a JCas), and even though 
the classes get loaded by the parent classloader (because the extension class 
path loader's classpath is ""), the generators for these classes are associated 
(in a hashmap) with the classloader in effect (that is, the UIMA Extension 
loader).  One possible "fix" for this is to have this process set the generator 
for the parent classloader(s) depending on what the "loading" classloader used 
was.  This sounds like a bug fix we could do in UIMA (assuming it's possible to 
detect the "loading" class loader - not sure if class.getClassloader returns 
the "initiating" or "loading" loader...

> JCas returning generic class instead of JCas cover class
> --------------------------------------------------------
>
>                 Key: UIMA-5054
>                 URL: https://issues.apache.org/jira/browse/UIMA-5054
>             Project: UIMA
>          Issue Type: Bug
>          Components: Collection Processing
>    Affects Versions: 2.8.1SDK
>            Reporter: Richard Eckart de Castilho
>             Fix For: 2.9.0SDK
>
>
> A DKPro Core user reported that when deploying an AE in a CPE 
> he was unable to access a JCas cover class in the 
> entityProcessComplete(...) CPE callback. See: 
> https://groups.google.com/d/msg/dkpro-core-user/-DtO5Ivnk9I/sjQAPPv1BwAJ
> {noformat}
>         public void entityProcessComplete(CAS cas, EntityProcessStatus 
> status) {
>             try {
>                 JCas jcas = cas.getJCas();
>                 // here getting a JCas cover class fails. Instead,
>                 // an AnnotationImpl is returned from the jcas.
>             } catch (CASException e) {
>                 e.printStackTrace();
>             }
>         }
> {noformat}
> The problem appears to be that the static CAS classloaders are restored
> *before* invoking the entityProcessComplete() callback (CPMEngine 3468):
> {noformat}
>       try {
>         if (null != cas)
>           ((CASImpl)cas).switchClassLoaderLockCas(statCL);
>         statCL.entityProcessComplete(cas, eps);
>       } finally {
>         if (null != cas) 
>           ((CASImpl)cas).restoreClassLoaderUnlockCas();
>       }
> {noformat}
> Is there any reason that the classloaders are switched out before invoking 
> the callback? If not, any objection if I change the code such that the 
> callback is invoked before the classloaders are switched out?
> {noformat}
> Thread [[Procesing Pipeline#7 Thread]::] (Suspended (breakpoint at line 1021 
> in CASImpl))     
>       CASImpl.setLocalFsGenerators(FSGenerator<FeatureStructure>[]) line: 
> 1021        
>       FSClassRegistry.swapInGeneratorsForClassLoader(ClassLoader, CASImpl) 
> line: 225  
>       JCasImpl.switchClassLoader(ClassLoader) line: 548       
>       CASImpl.switchClassLoader(ClassLoader) line: 4195       
>       CASImpl.switchClassLoaderLockCasCL(ClassLoader) line: 4183      
>       CASImpl.switchClassLoaderLockCas(Object) line: 4176     
>       CPMEngine.callEntityProcessCompleteWithCAS(StatusCallbackListener, CAS, 
> EntityProcessStatus) line: 3472 
>       ProcessingUnit.doNotifyListeners(Object, boolean, EntityProcessStatus) 
> line: 1650       
>       ProcessingUnit.notifyListeners(Object, boolean, EntityProcessStatus) 
> line: 1592 
>       ProcessingUnit.processNext(Object[], ProcessTrace) line: 917    
>       ProcessingUnit.run() line: 575  
> {noformat}



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to