uima-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Marshall Schor (JIRA)" <...@uima.apache.org>
Subject [jira] [Commented] (UIMA-5554) Strange exception when trying to get JCas FS class through reflection
Date Tue, 12 Sep 2017 13:27:01 GMT

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

Marshall Schor commented on UIMA-5554:

Thanks for the response; I think this dialog is helping to clarify some details (even in my
mind) :-)

First, re: the mental picture, in both v2 and v3, type systems (including committed ones)
*can* be shared among CASes - there's a concept of CAS Pools that supports this; it's useful
when running multiple copies of the same pipeline.

Ignoring that for the moment, and assuming 1 class loader, it is true that you can have multiple
pipelines, each with their own particular type system definition, installed into different
If you're not using JCas, then there is a "sharing" of the *built-in JCas classes*, like TOP
and Annotation and FSArray, etc.  These are arranged to be constant and sharable among the
various CAS's type systems.

Now, if you have some JCas classes, because of the above assumption of 1 class loader, these
are loaded *globally*.  If you want/need isolation, then you run with classLoaders (like servlets)
providing the isolation.  

Commit is an action done per type system, but it has a potentially global effect in that it
also loads the JCas classes it can find for those types.  These are loaded *globally* into
the current classloader - there's no mechanism in Java (other than using classloaders) to
isolate these..  I note that this is how v2 works, also.  

re: "In the call you have above, I somehow miss a reference to the CAS instance from which
the type system is obtained": 

You are correct - This is done using a hidden parameter, which is the type system whose data
is used when running the static initializers in JCas class being loaded.  This hidden parameter
is passed via a ThreadLocal, which is set during the type system commit, before calling the
code to find and load JCas classes associated with that type system.

Re: leaking information between CAS instances.  

There's no leaking of slot info in the type system information.  And, the JCas class for a
type, "Foo", only gets loaded once (globally) (again, per class loader).  This loading is
done with the "first" type system commit that has a type that corresponds to this particular
JCas class. This is also how v2 worked. 

In your scenario, if you do a type system commit in " a CAS with type X having feature x and
another CAS with type X having feature y":
  - if no JCas classes match type X, no JCas classes are loaded for it
  - if there's a JCas class definition in the classpath for type X, then the *first* typesystem
commit loads the JCas class, and it get initialized for that type system.
    -- When the 2nd type system is committed, the Java will find that JCas class already loaded,
and not load it again.

This was also the case in version 2.  Trying to use the same JCas class for multiple different
type systems having different definitions of the corresponding type is in the realm of undefined
behavior, depending a lot on specifics, ordering, etc.  It might partially work in some case,
not in others. 

One thing that would work, always, is the scenario where there are 
  - different type systems, 
  - different JCas classes, 
  - but no JCas name collisions (other than for classes which would be the same among all
the CASes, like Annotation, or MyTopLevelConcept, for instance).  

When CAS 1's type system was committed, it would load its JCas classes, and when CAS 2's type
system was committed, those (differently named) JCas classes would be loaded.

> Strange exception when trying to get JCas FS class through reflection
> ---------------------------------------------------------------------
>                 Key: UIMA-5554
>                 URL: https://issues.apache.org/jira/browse/UIMA-5554
>             Project: UIMA
>          Issue Type: Bug
>          Components: Core Java Framework
>    Affects Versions: 3.0.0SDK-beta
>            Reporter: Richard Eckart de Castilho
> I am trying to get a class object for a JCas FS type using reflection:
> {noformat}
> Class.forName(typeName);
> {noformat}
> However, it produces this strange error.
> {noformat}
> java.lang.ExceptionInInitializerError
> 	at java.lang.Class.forName0(Native Method)
> 	at java.lang.Class.forName(Class.java:264)
> ...
> Caused by: org.apache.uima.cas.CASRuntimeException: A JCas class field "sofa" is being
initialized by non-framework (user) code before Type System Commit for a type system with
a corresponding type. Either change the user load code to not do initialize, or to defer it
until after the type system commit.
> 	at org.apache.uima.cas.impl.TypeSystemImpl.getAdjustedFeatureOffset(TypeSystemImpl.java:2575)
> 	at org.apache.uima.jcas.cas.AnnotationBase.<clinit>(AnnotationBase.java:71)
> 	... 27 more
> {noformat}
> Is it considered harmful to try getting a class object for a JCas FS class?

This message was sent by Atlassian JIRA

View raw message