private List<Field> buildValidFieldsFromCachedFields (CachedField[] cachedFields, IntArray useAsm) { ArrayList<Field> fields = new ArrayList<Field>(cachedFields.length); for(CachedField f: cachedFields) { fields.add(f.field); useAsm.add((f.accessIndex > -1)?1:0); } return fields; }
private List<Field> buildValidFields (boolean transientFields, List<Field> allFields, ObjectMap context, IntArray useAsm) { List<Field> result = new ArrayList(allFields.size()); for (int i = 0, n = allFields.size(); i < n; i++) { Field field = allFields.get(i); int modifiers = field.getModifiers(); if (Modifier.isTransient(modifiers) != transientFields) continue; if (Modifier.isStatic(modifiers)) continue; if (field.isSynthetic() && ignoreSyntheticFields) continue; if (!field.isAccessible()) { if (!setFieldsAsAccessible) continue; try { field.setAccessible(true); } catch (AccessControlException ex) { continue; } } Optional optional = field.getAnnotation(Optional.class); if (optional != null && !context.containsKey(optional.value())) continue; result.add(field); // BOZO - Must be public? useAsm.add(!Modifier.isFinal(modifiers) && Modifier.isPublic(modifiers) && Modifier.isPublic(field.getType().getModifiers()) ? 1 : 0); } return result; }
private void createCachedFields (IntArray useAsm, List<Field> validFields, List<CachedField> cachedFields, int baseIndex) { if (useAsmEnabled || !useMemRegions) { for (int i = 0, n = validFields.size(); i < n; i++) { Field field = validFields.get(i); int accessIndex = -1; if (access != null && useAsm.get(baseIndex + i) == 1) accessIndex = ((FieldAccess)access).getIndex(field.getName()); cachedFields.add(newCachedField(field, cachedFields.size(), accessIndex)); } } else { unsafeUtil.createUnsafeCacheFieldsAndRegions(validFields, cachedFields, baseIndex, useAsm); } }
private List<Field> buildValidFields (boolean transientFields, List<Field> allFields, ObjectMap context, IntArray useAsm) { List<Field> result = new ArrayList(allFields.size()); for (int i = 0, n = allFields.size(); i < n; i++) { Field field = allFields.get(i); int modifiers = field.getModifiers(); if (Modifier.isTransient(modifiers) && !transientFields) continue; if (Modifier.isStatic(modifiers)) continue; if (field.isSynthetic() && ignoreSyntheticFields) continue; if (!field.isAccessible()) { if (!setFieldsAsAccessible) continue; try { field.setAccessible(true); } catch (AccessControlException ex) { continue; } } Optional optional = field.getAnnotation(Optional.class); if (optional != null && !context.containsKey(optional.value())) continue; result.add(field); // BOZO - Must be public? useAsm.add(!Modifier.isFinal(modifiers) && Modifier.isPublic(modifiers) && Modifier.isPublic(field.getType().getModifiers()) ? 1 : 0); } return result; }
/** Use Unsafe-based information about fields layout in memory to build a list of cached fields and memory regions representing * consecutive fields in memory */ public abstract void createUnsafeCacheFieldsAndRegions (List<Field> validFields, List<CachedField> cachedFields, int baseIndex, IntArray useAsm);
/** Called when the list of cached fields must be rebuilt. This is done any time settings are changed that affect which fields * will be used. It is called from the constructor for FieldSerializer, but not for subclasses. Subclasses must call this from * their constructor. */ protected void rebuildCachedFields () { if (TRACE && generics != null) trace("kryo", "generic type parameters are: " + Arrays.toString(generics)); if (type.isInterface()) { fields = new CachedField[0]; // No fields to serialize. return; } hasObjectFields = false; // For generic classes, generate a mapping from type variable names to the concrete types // This mapping is the same for the whole class. Generics genScope = buildGenericsScope(type, generics); genericsScope = genScope; // Push proper scopes at serializer construction time if (genericsScope != null) kryo.pushGenericsScope(type, genericsScope); // Collect all fields. List<Field> allFields = new ArrayList(); Class nextClass = type; while (nextClass != Object.class) { Field[] declaredFields = nextClass.getDeclaredFields(); if (declaredFields != null) { for (Field f : declaredFields) { if (Modifier.isStatic(f.getModifiers())) continue; allFields.add(f); } } nextClass = nextClass.getSuperclass(); } ObjectMap context = kryo.getContext(); IntArray useAsm = new IntArray(); // Sort fields by their offsets if (useMemRegions && !useAsmEnabled && unsafe() != null) { Field[] allFieldsArray = softFieldsByOffset(allFields); allFields = Arrays.asList(allFieldsArray); } // TODO: useAsm is modified as a side effect, this should be pulled out of buildValidFields List<Field> validFields = buildValidFields(false, allFields, context, useAsm); List<Field> validTransientFields = buildValidFields(true, allFields, context, useAsm); // Use ReflectASM for any public fields. if (useAsmEnabled && !Util.isAndroid && Modifier.isPublic(type.getModifiers()) && useAsm.indexOf(1) != -1) { try { access = FieldAccess.get(type); } catch (RuntimeException ignored) { } } List<CachedField> cachedFields = new ArrayList(validFields.size()); List<CachedField> cachedTransientFields = new ArrayList(validTransientFields.size()); createCachedFields(useAsm, validFields, cachedFields, 0); createCachedFields(useAsm, validTransientFields, cachedTransientFields, validFields.size()); Collections.sort(cachedFields, this); fields = cachedFields.toArray(new CachedField[cachedFields.size()]); Collections.sort(cachedTransientFields, this); transientFields = cachedTransientFields.toArray(new CachedField[cachedTransientFields.size()]); initializeCachedFields(); if (genericsScope != null) kryo.popGenericsScope(); }