简化部分代码
parent
5e3b188685
commit
eaae34d491
|
@ -42,5 +42,5 @@ public interface JfireSE
|
|||
|
||||
Object readByUnderInstanceIdFlag(ByteArray byteArray, byte flag);
|
||||
|
||||
void addCleanClassInfo(ClassInfo classInfo);
|
||||
void scheduleForClean(ClassInfo classInfo);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package com.jfirer.se2;
|
||||
|
||||
import com.jfirer.se2.classinfo.StaticClasInfo;
|
||||
import com.jfirer.se2.classinfo.RegisterClasInfo;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
|
@ -13,9 +13,9 @@ import java.util.concurrent.ConcurrentSkipListSet;
|
|||
public class JfireSEConfig
|
||||
{
|
||||
private boolean refTracking = false;
|
||||
private short staticClassId = 0;
|
||||
private StaticClasInfo[] clasInfos = new StaticClasInfo[10];
|
||||
private Set<Class<?>> set = new HashSet<>();
|
||||
private short staticClassId = 0;
|
||||
private RegisterClasInfo[] clasInfos = new RegisterClasInfo[10];
|
||||
private Set<Class<?>> set = new HashSet<>();
|
||||
private static Set<Class<?>> NO_NEED_TRACK_CLASS = new HashSet<>();
|
||||
|
||||
static
|
||||
|
@ -113,14 +113,14 @@ public class JfireSEConfig
|
|||
|
||||
public JfireSE build()
|
||||
{
|
||||
StaticClasInfo[] array = set.stream().map(this::resolve).toArray(StaticClasInfo[]::new);
|
||||
RegisterClasInfo[] array = set.stream().map(this::resolve).toArray(RegisterClasInfo[]::new);
|
||||
return new JfireSEImpl(refTracking, array);
|
||||
}
|
||||
|
||||
private StaticClasInfo resolve(Class<?> clazz)
|
||||
private RegisterClasInfo resolve(Class<?> clazz)
|
||||
{
|
||||
StaticClasInfo staticClasInfo = new StaticClasInfo(staticClassId, clazz, NO_NEED_TRACK_CLASS.contains(clazz) ? false : refTracking);
|
||||
RegisterClasInfo registerClasInfo = new RegisterClasInfo(staticClassId, clazz, NO_NEED_TRACK_CLASS.contains(clazz) ? false : refTracking);
|
||||
staticClassId++;
|
||||
return staticClasInfo;
|
||||
return registerClasInfo;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,46 +2,43 @@ package com.jfirer.se2;
|
|||
|
||||
import com.jfirer.se2.classinfo.ClassInfo;
|
||||
import com.jfirer.se2.classinfo.DynamicClassInfo;
|
||||
import com.jfirer.se2.classinfo.StaticClasInfo;
|
||||
import com.jfirer.se2.classinfo.RegisterClasInfo;
|
||||
import com.jfirer.se2.serializer.Serializer;
|
||||
import com.jfirer.se2.serializer.SerializerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
public class JfireSEImpl implements JfireSE
|
||||
{
|
||||
private final boolean refTracking;
|
||||
private final int staticClassId;
|
||||
private int dynamicClassId;
|
||||
/**
|
||||
* 用于存储序列化相关的 classInfo
|
||||
*/
|
||||
private ClassInfo[] serializedClassInfos;
|
||||
private ClassInfo[] storedClassInfos;
|
||||
/**
|
||||
* 用于存储逆序列化过程中的临时信息
|
||||
* 用于存储逆序列化过程中的临时信息。
|
||||
* 这些信息不需要清理,因为每一次逆序列化,对首次出现的类都会有 classId,可以用这个 classId 直接在数组中设置元素。这样后续通过下标的到的值都是正确的。
|
||||
* 因此这个数组中的元素部分是本次序列化中正确的,部分是之前残余的。但是之前残余的本次都不会被使用到的,因此该数组不需要清理。
|
||||
*/
|
||||
private ClassInfo[] deSerializedClassInfos;
|
||||
private ByteArray byteArray = new ByteArray(1000);
|
||||
private final ByteArray byteArray = new ByteArray(1000);
|
||||
private ClassInfo classInfoCache;
|
||||
private Map<Class<?>, ClassInfo> classInfoMap = new HashMap<>();
|
||||
private SerializerFactory serializerFactory = new SerializerFactory(this);
|
||||
private Map<byte[], ClassInfo> classInfoCacheMap = new HashMap<>();
|
||||
private Map<String, Class<?>> classNameBytesCache = new HashMap<>();
|
||||
private List<ClassInfo> cleanClassInfos = new ArrayList<>();
|
||||
private final Map<Class<?>, ClassInfo> classInfoMap = new IdentityHashMap<>();
|
||||
private final SerializerFactory serializerFactory = new SerializerFactory(this);
|
||||
private final Map<String, Class<?>> classNameBytesCache = new HashMap<>();
|
||||
private final List<ClassInfo> scheduleForCleans = new ArrayList<>();
|
||||
|
||||
public JfireSEImpl(boolean refTracking, StaticClasInfo[] staticClasInfos)
|
||||
public JfireSEImpl(boolean refTracking, RegisterClasInfo[] registerClasInfos)
|
||||
{
|
||||
this.refTracking = refTracking;
|
||||
this.staticClassId = staticClasInfos.length - 1;
|
||||
serializedClassInfos = new ClassInfo[staticClasInfos.length * 2];
|
||||
deSerializedClassInfos = new ClassInfo[serializedClassInfos.length];
|
||||
System.arraycopy(staticClasInfos, 0, serializedClassInfos, 0, staticClasInfos.length);
|
||||
System.arraycopy(staticClasInfos, 0, deSerializedClassInfos, 0, staticClasInfos.length);
|
||||
this.refTracking = refTracking;
|
||||
int staticClassId = registerClasInfos.length - 1;
|
||||
storedClassInfos = new ClassInfo[registerClasInfos.length * 2];
|
||||
deSerializedClassInfos = new ClassInfo[storedClassInfos.length];
|
||||
System.arraycopy(registerClasInfos, 0, storedClassInfos, 0, registerClasInfos.length);
|
||||
System.arraycopy(registerClasInfos, 0, deSerializedClassInfos, 0, registerClasInfos.length);
|
||||
dynamicClassId = staticClassId + 1;
|
||||
for (StaticClasInfo each : staticClasInfos)
|
||||
for (RegisterClasInfo each : registerClasInfos)
|
||||
{
|
||||
each.setSerializer(serializerFactory.getSerializer(each.getClazz()));
|
||||
each.setJfireSE(this);
|
||||
|
@ -61,29 +58,30 @@ public class JfireSEImpl implements JfireSE
|
|||
classInfoCache = classInfo;
|
||||
return classInfo;
|
||||
}
|
||||
if (dynamicClassId == serializedClassInfos.length)
|
||||
if (dynamicClassId == storedClassInfos.length)
|
||||
{
|
||||
ClassInfo[] tmp = new ClassInfo[serializedClassInfos.length * 2];
|
||||
System.arraycopy(serializedClassInfos, 0, tmp, 0, serializedClassInfos.length);
|
||||
serializedClassInfos = tmp;
|
||||
ClassInfo[] tmp = new ClassInfo[storedClassInfos.length * 2];
|
||||
System.arraycopy(storedClassInfos, 0, tmp, 0, storedClassInfos.length);
|
||||
storedClassInfos = tmp;
|
||||
}
|
||||
DynamicClassInfo dynamicClassInfo = new DynamicClassInfo((short) dynamicClassId, clazz, refTracking);
|
||||
dynamicClassInfo.setJfireSE(this);
|
||||
serializedClassInfos[dynamicClassId] = dynamicClassInfo;
|
||||
storedClassInfos[dynamicClassId] = dynamicClassInfo;
|
||||
dynamicClassId++;
|
||||
Serializer serializer = serializerFactory.getSerializer(clazz);
|
||||
dynamicClassInfo.setSerializer(serializer);
|
||||
classInfoCache = dynamicClassInfo;
|
||||
classInfoMap.put(clazz, dynamicClassInfo);
|
||||
return dynamicClassInfo;
|
||||
}
|
||||
|
||||
private void resetSerialized()
|
||||
private void clean()
|
||||
{
|
||||
for (ClassInfo each : cleanClassInfos)
|
||||
for (ClassInfo each : scheduleForCleans)
|
||||
{
|
||||
each.reset();
|
||||
each.clean();
|
||||
}
|
||||
cleanClassInfos.clear();
|
||||
scheduleForCleans.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -100,7 +98,7 @@ public class JfireSEImpl implements JfireSE
|
|||
ClassInfo classInfo = getOrCreateClassInfo(instance.getClass());
|
||||
classInfo.write(byteArray, instance);
|
||||
byte[] array = byteArray.toArray();
|
||||
resetSerialized();
|
||||
clean();
|
||||
return array;
|
||||
}
|
||||
|
||||
|
@ -142,7 +140,7 @@ public class JfireSEImpl implements JfireSE
|
|||
}
|
||||
default -> throw new RuntimeException("未知的序列化类型");
|
||||
};
|
||||
resetSerialized();
|
||||
clean();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -163,12 +161,7 @@ public class JfireSEImpl implements JfireSE
|
|||
classNameBytesCache.put(className, aClass);
|
||||
}
|
||||
ClassInfo classInfo = getOrCreateClassInfo(aClass);
|
||||
if (deSerializedClassInfos == null)
|
||||
{
|
||||
deSerializedClassInfos = new ClassInfo[classId + 1];
|
||||
deSerializedClassInfos[classId] = classInfo;
|
||||
}
|
||||
else if (classId >= deSerializedClassInfos.length)
|
||||
if (classId >= deSerializedClassInfos.length)
|
||||
{
|
||||
int newLen = deSerializedClassInfos.length * 2;
|
||||
newLen = newLen > classId ? newLen : classId + 1;
|
||||
|
@ -227,8 +220,8 @@ public class JfireSEImpl implements JfireSE
|
|||
}
|
||||
|
||||
@Override
|
||||
public void addCleanClassInfo(ClassInfo classInfo)
|
||||
public void scheduleForClean(ClassInfo classInfo)
|
||||
{
|
||||
cleanClassInfos.add(classInfo);
|
||||
scheduleForCleans.add(classInfo);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,13 +6,10 @@ import com.jfirer.se2.serializer.Serializer;
|
|||
import io.github.karlatemp.unsafeaccessor.Unsafe;
|
||||
import lombok.Data;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
@Data
|
||||
public abstract class ClassInfo implements RefTracking
|
||||
{
|
||||
protected final short classId;
|
||||
protected final byte[] classNameBytes;
|
||||
protected final byte[] classNameStringBytes;
|
||||
protected final byte classNameStringCoder;
|
||||
protected final Class<?> clazz;
|
||||
|
@ -21,7 +18,7 @@ public abstract class ClassInfo implements RefTracking
|
|||
protected int refTrackingIndex = 0;
|
||||
protected Serializer serializer;
|
||||
protected JfireSE jfireSE;
|
||||
protected boolean firstSerialized = true;
|
||||
protected boolean needClean = false;
|
||||
protected static final Unsafe UNSAFE = Unsafe.getUnsafe();
|
||||
|
||||
public ClassInfo(short classId, Class<?> clazz, boolean refTrack)
|
||||
|
@ -29,7 +26,6 @@ public abstract class ClassInfo implements RefTracking
|
|||
this.classId = classId;
|
||||
this.clazz = clazz;
|
||||
this.refTrack = refTrack;
|
||||
classNameBytes = clazz.getName().getBytes(StandardCharsets.UTF_8);
|
||||
classNameStringBytes = (byte[]) UNSAFE.getReference(clazz.getName(), ByteArray.STRING_VALUE_FIELD_OFFSET);
|
||||
classNameStringCoder = UNSAFE.getByte(clazz.getName(), ByteArray.STRING_CODER_FIELD_OFFSET);
|
||||
}
|
||||
|
@ -58,7 +54,7 @@ public abstract class ClassInfo implements RefTracking
|
|||
return -1;
|
||||
}
|
||||
|
||||
public void reset()
|
||||
public void clean()
|
||||
{
|
||||
if (refTrackingIndex != 0)
|
||||
{
|
||||
|
@ -68,7 +64,7 @@ public abstract class ClassInfo implements RefTracking
|
|||
}
|
||||
refTrackingIndex = 0;
|
||||
}
|
||||
firstSerialized = true;
|
||||
needClean = false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -118,10 +114,10 @@ public abstract class ClassInfo implements RefTracking
|
|||
public Object readWithTrack(ByteArray byteArray)
|
||||
{
|
||||
Object result = serializer.read(byteArray, this);
|
||||
if (firstSerialized)
|
||||
if (!needClean)
|
||||
{
|
||||
firstSerialized = false;
|
||||
jfireSE.addCleanClassInfo(this);
|
||||
needClean = true;
|
||||
jfireSE.scheduleForClean(this);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -22,18 +22,19 @@ public class DynamicClassInfo extends ClassInfo
|
|||
@Override
|
||||
public void write(ByteArray byteArray, Object instance)
|
||||
{
|
||||
if (firstSerialized)
|
||||
//如果needClean 为 false,意味着这个 classInfo 是首次输出。后续必然需要清理。
|
||||
if (!needClean)
|
||||
{
|
||||
if (refTrack)
|
||||
{
|
||||
addTracking(instance);
|
||||
}
|
||||
firstSerialized = false;
|
||||
byteArray.put(JfireSE.NAME_ID_CONTENT_TRACK);
|
||||
byteArray.writeString(classNameStringBytes, classNameStringCoder);
|
||||
byteArray.writePositiveVarInt(classId);
|
||||
serializer.writeBytes(byteArray, instance);
|
||||
jfireSE.addCleanClassInfo(this);
|
||||
needClean = true;
|
||||
jfireSE.scheduleForClean(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -3,9 +3,12 @@ package com.jfirer.se2.classinfo;
|
|||
import com.jfirer.se2.ByteArray;
|
||||
import com.jfirer.se2.JfireSE;
|
||||
|
||||
public class StaticClasInfo extends ClassInfo
|
||||
/**
|
||||
* 事先注册的类,这样在序列化的时候只需要序列化 classId 即可。
|
||||
*/
|
||||
public class RegisterClasInfo extends ClassInfo
|
||||
{
|
||||
public StaticClasInfo(short classId, Class<?> clazz, boolean refTracking)
|
||||
public RegisterClasInfo(short classId, Class<?> clazz, boolean refTracking)
|
||||
{
|
||||
super(classId, clazz, refTracking);
|
||||
}
|
||||
|
@ -28,10 +31,10 @@ public class StaticClasInfo extends ClassInfo
|
|||
byteArray.writePositiveVarInt(classId);
|
||||
byteArray.writePositiveVarInt(i);
|
||||
}
|
||||
if (firstSerialized)
|
||||
if (!needClean)
|
||||
{
|
||||
firstSerialized = false;
|
||||
jfireSE.addCleanClassInfo(this);
|
||||
needClean = true;
|
||||
jfireSE.scheduleForClean(this);
|
||||
}
|
||||
}
|
||||
else
|
|
@ -10,6 +10,7 @@ public class Profile
|
|||
JfireSE jfireSE = JfireSE.supportRefTracking(true).build();
|
||||
TestData data = new TestData().setTestDataSm(new TestDataSm()).setTestDataSm2(new TestDataSm2());
|
||||
byte[] serialize = jfireSE.serialize(data);
|
||||
Object unuse = jfireSE.deSerialize(serialize);
|
||||
|
||||
@Test
|
||||
public void test()
|
||||
|
|
Loading…
Reference in New Issue