You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@uima.apache.org by sc...@apache.org on 2017/10/09 13:55:37 UTC
svn commit: r1811572 - in
/uima/uv3/uimaj-v3/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl:
FSClassRegistry.java TypeSystemImpl.java
Author: schor
Date: Mon Oct 9 13:55:37 2017
New Revision: 1811572
URL: http://svn.apache.org/viewvc?rev=1811572&view=rev
Log:
[UIMA-5607] change method of setup for constants in jcas classes to use reflection, rather than depending on static initializers running in the context of a type system commit.
Modified:
uima/uv3/uimaj-v3/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSClassRegistry.java
uima/uv3/uimaj-v3/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/TypeSystemImpl.java
Modified: uima/uv3/uimaj-v3/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSClassRegistry.java
URL: http://svn.apache.org/viewvc/uima/uv3/uimaj-v3/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSClassRegistry.java?rev=1811572&r1=1811571&r2=1811572&view=diff
==============================================================================
--- uima/uv3/uimaj-v3/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSClassRegistry.java (original)
+++ uima/uv3/uimaj-v3/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSClassRegistry.java Mon Oct 9 13:55:37 2017
@@ -140,10 +140,10 @@ public abstract class FSClassRegistry {
// must precede first (static) use
static private ThreadLocal<List<ErrorReport>> errorSet = new ThreadLocal<>();
- /**
- * Map (per class loader) from JCas Classes, to all callSites in that JCas class
- */
- public static final Map<Class<? extends TOP>, ArrayList<Entry<String, MutableCallSite>>> callSites_all_JCasClasses = new HashMap<>();
+// /**
+// * Map (per class loader) from JCas Classes, to all callSites in that JCas class
+// */
+// public static final Map<Class<? extends TOP>, ArrayList<Entry<String, MutableCallSite>>> callSites_all_JCasClasses = new HashMap<>();
/**
* One instance per UIMA Type per class loader
@@ -278,6 +278,8 @@ public abstract class FSClassRegistry {
}
}
+ callSites_toSync.clear();
+
/**
* copy in built-ins
* update t2jcci (if not already loaded) with load info for type
@@ -294,6 +296,7 @@ public abstract class FSClassRegistry {
type_to_jcasClassInfo.put(jcasClass.getCanonicalName(), jcas_class_info);
}
setTypeFromJCasIDforBuiltIns(jcas_class_info, ts, typecode);
+ updateAllCallSitesForJCasClass((Class<? extends TOP>) jcasClass, ts.getTypeForCode(typecode));
}
}
@@ -327,7 +330,7 @@ public abstract class FSClassRegistry {
throw new UIMARuntimeException(e, UIMARuntimeException.INTERNAL_ERROR);
}
- callSites_toSync.clear();
+
maybeLoadJCasAndSubtypes(ts, ts.topType, type_to_jcasClassInfo.get(TOP.class.getCanonicalName()), cl, type_to_jcasClassInfo);
MutableCallSite[] sync = callSites_toSync.toArray(new MutableCallSite[callSites_toSync.size()]);
@@ -472,48 +475,21 @@ public abstract class FSClassRegistry {
* @return the loaded / resolved class
*/
private static Class<?> maybeLoadJCas(TypeImpl ti, ClassLoader cl) {
- Class<?> clazz = null;
+ Class<? extends TOP> clazz = null;
String className = Misc.typeName2ClassName(ti.getName());
try {
- TypeSystemImpl.typeBeingLoadedThreadLocal.set(ti);
- clazz = Class.forName(className, true, cl);
- ArrayList<Entry<String, MutableCallSite>> callsites = callSites_all_JCasClasses.get(clazz);
- if (null != callsites) {
- for (Entry<String, MutableCallSite> e : callsites) {
- final int index = TypeSystemImpl.getAdjustedFeatureOffset(e.getKey());
- if (index == -1) {
- continue; // a feature in the JCas class doesn't exist in the currently loaded type system
- // skip setting it. If code uses this, a runtime error will happen.
- }
- final int prev = (int) e.getValue().getTarget().invokeExact();
-
- if (prev == -1) {
- MethodHandle mh_constant = getConstantIntMethodHandle(index);
-
- e.getValue().setTarget(mh_constant);
- callSites_toSync.add(e.getValue());
- } else if (prev != index) {
- throw new UIMA_IllegalStateException(UIMA_IllegalStateException.JCAS_INCOMPATIBLE_TYPE_SYSTEMS,
- new Object[] {ti.getName(), e.getKey()});
- }
-
- }
- }
+ clazz = (Class<? extends TOP>) Class.forName(className, true, cl);
+ updateAllCallSitesForJCasClass(clazz, ti);
} catch (ClassNotFoundException e) {
// Class not found is normal, if there is no JCas for this class
- } catch (Throwable e1) {
- if (e1 instanceof UIMA_IllegalStateException) {
- throw (UIMA_IllegalStateException) e1;
- }
- throw Misc.internalError(); // from invokeExact
} finally {
TypeSystemImpl.typeBeingLoadedThreadLocal.set(null);
}
return clazz;
}
- private static synchronized MethodHandle getConstantIntMethodHandle(int i) {
+ static synchronized MethodHandle getConstantIntMethodHandle(int i) {
MethodHandle mh = Misc.getWithExpand(methodHandlesForInt, i);
if (mh == null) {
methodHandlesForInt.set(i, mh = MethodHandles.constant(int.class, i));
@@ -682,7 +658,7 @@ public abstract class FSClassRegistry {
// static boolean isFieldInClass(Feature feat, Class<?> clazz) {
// try {
-// return null != clazz.getDeclaredField("_FI_" + feat.getShortName());
+// return null != clazz.getDeclaredField("_FC_" + feat.getShortName());
// } catch (NoSuchFieldException e) {
// return false;
// }
@@ -705,7 +681,7 @@ public abstract class FSClassRegistry {
* Checks that a JCas class definition conforms to the current type in the current type system.
* Checks that the superclass chain contains some match to the super type chain.
* Checks that the return value for the getters for features matches the feature's range.
- * Checks that static _FI_xxx values from the JCas class == the adjusted feature offsets in the type system
+ * Checks that static _FC_xxx values from the JCas class == the adjusted feature offsets in the type system
*
* @param clazz - the JCas class to check
* @param tsi -
@@ -797,32 +773,38 @@ public abstract class FSClassRegistry {
}
}
}
-
- for (Field f : clazz.getDeclaredFields()) {
- String fname = f.getName();
- if (fname.length() <= 5 || !fname.startsWith("_FI_")) continue;
- String featName = fname.substring(4);
- FeatureImpl fi = ti.getFeatureByBaseName(featName);
- if (fi == null) {
- add2errors(errorSet,
- new CASRuntimeException(CASRuntimeException.JCAS_FIELD_MISSING_IN_TYPE_SYSTEM, clazz.getName(), featName),
- false); // don't throw on this error, field is set to -1 and will throw if trying to use it
- } else {
- int staticOffsetInClass = Misc.getPrivateStaticIntFieldNoInherit(clazz, fname);
- if (fi.getAdjustedOffset() != staticOffsetInClass) {
- /** In JCAS class "{0}", UIMA field "{1}" was set up when this class was previously loaded and initialized, to have
- * an adjusted offset of "{2}" but now the feature has a different adjusted offset of "{3}"; this may be due to
- * something else other than type system commit actions loading and initializing the JCas class, or to
- * having a different non-compatible type system for this class, trying to use a common JCas cover class, which is not supported. */
+ try {
+ for (Field f : clazz.getDeclaredFields()) {
+ String fname = f.getName();
+ if (fname.length() <= 5 || !fname.startsWith("_FC_")) continue;
+ String featName = fname.substring(4);
+ FeatureImpl fi = ti.getFeatureByBaseName(featName);
+ if (fi == null) {
add2errors(errorSet,
- new CASRuntimeException(CASRuntimeException.JCAS_FIELD_ADJ_OFFSET_CHANGED,
- clazz.getName(),
- fi.getName(),
- Integer.valueOf(staticOffsetInClass),
- Integer.valueOf(fi.getAdjustedOffset())),
- staticOffsetInClass != -1); // throw unless static offset is -1, in that case, a runtime error will occur if it is usedd
- }
- }
+ new CASRuntimeException(CASRuntimeException.JCAS_FIELD_MISSING_IN_TYPE_SYSTEM, clazz.getName(), featName),
+ false); // don't throw on this error, field is set to -1 and will throw if trying to use it
+ } else {
+ Field mhf = clazz.getDeclaredField("_FH_" + featName);
+ mhf.setAccessible(true);
+ MethodHandle mh = (MethodHandle) mhf.get(null);
+ int staticOffsetInClass = (int) mh.invokeExact();
+ if (fi.getAdjustedOffset() != staticOffsetInClass) {
+ /** In JCAS class "{0}", UIMA field "{1}" was set up when this class was previously loaded and initialized, to have
+ * an adjusted offset of "{2}" but now the feature has a different adjusted offset of "{3}"; this may be due to
+ * something else other than type system commit actions loading and initializing the JCas class, or to
+ * having a different non-compatible type system for this class, trying to use a common JCas cover class, which is not supported. */
+ add2errors(errorSet,
+ new CASRuntimeException(CASRuntimeException.JCAS_FIELD_ADJ_OFFSET_CHANGED,
+ clazz.getName(),
+ fi.getName(),
+ Integer.valueOf(staticOffsetInClass),
+ Integer.valueOf(fi.getAdjustedOffset())),
+ staticOffsetInClass != -1); // throw unless static offset is -1, in that case, a runtime error will occur if it is usedd
+ } // end of offset changed
+ } // end of feature check
+ } // end of for loop
+ } catch (Throwable e) {
+ throw new RuntimeException(e);
}
}
@@ -918,5 +900,42 @@ public abstract class FSClassRegistry {
return true;
}
+ private static void updateAllCallSitesForJCasClass(Class<? extends TOP> clazz, TypeImpl type) {
+ try {
+ Field[] fields = clazz.getDeclaredFields();
+
+ for (Field field : fields) {
+ String fieldName = field.getName();
+ if (fieldName.startsWith("_FC_")) {
+
+ String featureName = fieldName.substring("_FC_".length());
+ final int index = TypeSystemImpl.getAdjustedFeatureOffset(type, featureName);
+ if (index == -1) {
+ continue; // a feature defined in the JCas class doesn't exist in the currently loaded type
+ } // skip setting it. If code uses this, a runtime error will happen.
+
+ MutableCallSite c;
+ field.setAccessible(true);
+ c = (MutableCallSite) field.get(null);
+
+ if (c == null) { // happens when first load of TypeSystemImpl is from JCas class ref
+ continue; // will be set later when type system is committed.
+ }
+
+ int prev = (int) c.getTarget().invokeExact();
+ if (prev == -1) {
+ MethodHandle mh_constant = getConstantIntMethodHandle(index);
+ c.setTarget(mh_constant);
+ callSites_toSync.add(c);
+ } else if (prev != index) {
+ throw new UIMA_IllegalStateException(UIMA_IllegalStateException.JCAS_INCOMPATIBLE_TYPE_SYSTEMS,
+ new Object[] {type.getName(), featureName});
+ }
+ }
+ }
+ } catch (Throwable e) {
+ Misc.internalError(e); // never happen
+ }
+ }
}
\ No newline at end of file
Modified: uima/uv3/uimaj-v3/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/TypeSystemImpl.java
URL: http://svn.apache.org/viewvc/uima/uv3/uimaj-v3/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/TypeSystemImpl.java?rev=1811572&r1=1811571&r2=1811572&view=diff
==============================================================================
--- uima/uv3/uimaj-v3/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/TypeSystemImpl.java (original)
+++ uima/uv3/uimaj-v3/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/TypeSystemImpl.java Mon Oct 9 13:55:37 2017
@@ -38,7 +38,6 @@ import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.invoke.MutableCallSite;
import java.lang.ref.WeakReference;
-import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -48,7 +47,6 @@ import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.Map.Entry;
import java.util.Set;
import java.util.Vector;
import java.util.WeakHashMap;
@@ -2589,8 +2587,7 @@ public class TypeSystemImpl implements T
// Class<?> getJCasClass(int typecode) {
// return jcasClassesInfo[typecode].jcasClass;
// }
-
- /**
+ /**
* This code is run when a JCas class is loaded and resolved, for the first time, as part of type system commit, or
* as part of statically loading the FSClassRegister class (where this is done for all the built-ins, once).
* It looks up the offset value in the type system (via a thread-local)
@@ -2613,8 +2610,14 @@ public class TypeSystemImpl implements T
* Class.forName("myJCasClass", false, this.getClass().getClassLoader()).*/
throw new CASRuntimeException(CASRuntimeException.JCAS_CLASS_INITIALIZED_BEFORE_TYPE_SYSTEM_COMMIT);
}
+
FeatureImpl fi = type.getFeatureByBaseName(featName);
- return (fi == null) ? -1 : fi.getAdjustedOffset();
+ return (fi == null) ? -1 : fi.getAdjustedOffset();
+ }
+
+ static synchronized int getAdjustedFeatureOffset(TypeImpl type, String featName) {
+ FeatureImpl fi = type.getFeatureByBaseName(featName);
+ return (fi == null) ? -1 : fi.getAdjustedOffset();
}
/**
@@ -2654,27 +2657,30 @@ public class TypeSystemImpl implements T
/**
* Creates and returns a new MutableCallSite,
- * recording it in list of all callsites for this type, in a map by typename
- *
- * Done this way because
- * - can't be a classloader-wide list of call sites - some might not be associated with this type system
- * - can't be a typesystem-wide list of call sites - the JCas class might be used by multiple type systems
- * and the first one to load it would set this value.
- * - has to be pairs of feature name, call-site, in order to get the value to set, later
- * -- doesn't need to be a hashmap, can be an arraylist of entry
- * Type being loaded may not be known at this point.
+// * recording it in list of all callsites for this type, in a map by typename
+// *
+// * Done this way because
+// * - can't be a classloader-wide list of call sites - some might not be associated with this type system
+// * - can't be a typesystem-wide list of call sites - the JCas class might be used by multiple type systems
+// * and the first one to load it would set this value.
+// * - has to be pairs of feature name, call-site, in order to get the value to set, later
+// * -- doesn't need to be a hashmap, can be an arraylist of entry
+// * Type being loaded may not be known at this point.
* @param clazz the JCas class
* @param featName the short name of the feature
* @return the created callsite
*/
- public static MutableCallSite createCallSite(Class<? extends TOP> clazz, String featName) {
- MutableCallSite callSite = new MutableCallSite(MethodType.methodType(int.class));
+ public final static MutableCallSite createCallSite(Class<? extends TOP> clazz, String featName) {
+ MutableCallSite callSite = new MutableCallSite(MethodType.methodType(int.class));
callSite.setTarget(MHC_MINUS_1); // for error checking
- ArrayList<Entry<String, MutableCallSite>> callSitesForType = FSClassRegistry.callSites_all_JCasClasses.computeIfAbsent(clazz, k -> new ArrayList<>());
- callSitesForType.add(new AbstractMap.SimpleEntry<String, MutableCallSite>(featName, callSite));
+// ArrayList<Entry<String, MutableCallSite>> callSitesForType = FSClassRegistry.callSites_all_JCasClasses.computeIfAbsent(clazz, k -> new ArrayList<>());
+// callSitesForType.add(new AbstractMap.SimpleEntry<String, MutableCallSite>(featName, callSite));
return callSite;
}
+// private static boolean isBuiltIn(Class<? extends TOP> clazz) {
+// return BuiltinTypeKinds.creatableBuiltinJCasClassNames.contains(clazz.getName());
+// }
// /**
// * Get a list of types which have OID feature, filtered down to being just the top-most
// * (in the type hierarchy)