功能完善,并且提供了一个编译输出的版本,性能强大。在简单类的测试中,超过了 Fury

master
linbin 2024-09-10 17:34:14 +08:00
parent ab14e5b94d
commit 9a44742544
18 changed files with 605 additions and 186 deletions

View File

@ -37,7 +37,7 @@
<dependency>
<groupId>com.jfirer</groupId>
<artifactId>baseutil</artifactId>
<version>1.1.7-SNAPSHOT</version>
<version>1.1.8</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>

View File

@ -4,7 +4,10 @@ import com.jfirer.baseutil.reflect.ReflectUtil;
import com.jfirer.fse.InternalByteArray;
import io.github.karlatemp.unsafeaccessor.Unsafe;
import java.lang.invoke.*;
import java.lang.invoke.LambdaMetafactory;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.nio.ByteOrder;
import java.util.function.BiFunction;
@ -802,7 +805,7 @@ public class ByteArray
ensureNewWriterIndex(idx + 8 + numBytes);
idx += writePositiveVarIntWithoutEnsure(numBytes);
final long destAddr = BYTE_ARRAY_OFFSET + idx;
copyMemory(arr, arrOffset, array, destAddr, numBytes);
copyMemory(arr, BYTE_ARRAY_OFFSET + arrOffset, array, destAddr, numBytes);
writerIndex = idx + numBytes;
}
@ -816,7 +819,7 @@ public class ByteArray
throw new IndexOutOfBoundsException(String.format("readerIndex(%d) + length(%d) exceeds size(%d): %s", readerIdx, numBytes, writerIndex, this));
}
final byte[] arr = new byte[numBytes];
System.arraycopy(array, BYTE_ARRAY_OFFSET + readerIdx, arr, 0, numBytes);
System.arraycopy(array, readerIdx, arr, 0, numBytes);
readerIndex = readerIdx + numBytes;
return arr;
}

View File

@ -58,7 +58,7 @@ public class JfireSEConfig
private StaticClasInfo resolve(Class<?> clazz)
{
StaticClasInfo staticClasInfo = new StaticClasInfo(staticClassId, clazz.getName(), clazz, refTracking);
StaticClasInfo staticClasInfo = new StaticClasInfo(staticClassId, clazz, refTracking);
staticClassId++;
return staticClasInfo;
}

View File

@ -6,21 +6,27 @@ import com.jfirer.se2.classinfo.StaticClasInfo;
import com.jfirer.se2.serializer.Serializer;
import com.jfirer.se2.serializer.SerializerFactory;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
public class JfireSEImpl implements JfireSE
{
private final boolean refTracking;
private final int staticClassId;
private int dyncmicClassId;
private final boolean refTracking;
private final int staticClassId;
private int dyncmicClassId;
/**
* classInfo
*/
private ClassInfo[] serializedClassInfos;
private ClassInfo[] serializedClassInfos;
/**
*
*/
private ClassInfo[] deSerializedClassInfos;
private SerializerFactory serializerFactory = new SerializerFactory();
private ByteArray byteArray = new ByteArray(1000);
private ClassInfo[] deSerializedClassInfos;
private SerializerFactory serializerFactory = new SerializerFactory();
private ByteArray byteArray = new ByteArray(1000);
private ClassInfo classInfoCache;
private Map<Class<?>, ClassInfo> classInfoMap = new HashMap<>();
public JfireSEImpl(boolean refTracking, StaticClasInfo[] staticClasInfos)
{
@ -35,12 +41,15 @@ public class JfireSEImpl implements JfireSE
public ClassInfo getForSerialize(Class<?> clazz)
{
for (int i = 0; i < dyncmicClassId; i++)
if (classInfoCache != null && classInfoCache.getClazz() == clazz)
{
if (serializedClassInfos[i].getClazz() == clazz)
{
return serializedClassInfos[i];
}
return classInfoCache;
}
ClassInfo classInfo = classInfoMap.get(clazz);
if (classInfo != null)
{
classInfoCache = classInfo;
return classInfo;
}
if (dyncmicClassId == serializedClassInfos.length)
{
@ -48,11 +57,12 @@ public class JfireSEImpl implements JfireSE
System.arraycopy(serializedClassInfos, 0, tmp, 0, serializedClassInfos.length);
serializedClassInfos = tmp;
}
DynamicClassInfo dynamicClassInfo = new DynamicClassInfo((short) dyncmicClassId, clazz.getName(), clazz, refTracking);
DynamicClassInfo dynamicClassInfo = new DynamicClassInfo((short) dyncmicClassId, clazz, refTracking);
serializedClassInfos[dyncmicClassId] = dynamicClassInfo;
dyncmicClassId++;
Serializer serializer = serializerFactory.getSerializer(clazz, this);
dynamicClassInfo.setSerializer(serializer);
classInfoCache = dynamicClassInfo;
return dynamicClassInfo;
}
@ -95,36 +105,67 @@ public class JfireSEImpl implements JfireSE
{
case JfireSE.NAME_ID_CONTENT_TRACK ->
{
String className = byteArray.readString();
int classId = byteArray.readVarInt();
try
{
Class<?> clazz = Class.forName(className);
ClassInfo classInfo = getForSerialize(clazz);
if (deSerializedClassInfos == null)
{
deSerializedClassInfos = new ClassInfo[classId + 1];
deSerializedClassInfos[classId] = classInfo;
}
else if (classId >= deSerializedClassInfos.length)
{
int newLen = deSerializedClassInfos.length * 2;
newLen = newLen > classId ? newLen : classId + 1;
ClassInfo[] tmp = new ClassInfo[newLen];
System.arraycopy(deSerializedClassInfos, 0, tmp, 0, deSerializedClassInfos.length);
deSerializedClassInfos = tmp;
deSerializedClassInfos[classId] = classInfo;
}
else
{
deSerializedClassInfos[classId] = classInfo;
}
}
catch (ClassNotFoundException e)
{
throw new RuntimeException(e);
}
byte[] classNameBytes = stream.readBytesWithSizeEmbedded();
int classId = stream.readVarInt();
ClassInfo classInfo = getForDeSerialize(classNameBytes, classId);
return classInfo.readWithTrack(stream);
}
case JfireSE.NAME_ID_CONTENT_UN_TRACK ->
{
byte[] classNameBytes = stream.readBytesWithSizeEmbedded();
int classId = stream.readVarInt();
return getForDeSerialize(classNameBytes, classId).readWithoutTrack(stream);
}
case JfireSE.id_content_track ->
{
int classId = stream.readVarInt();
ClassInfo classInfo = getForDeSerialize(classId);
return classInfo.readWithTrack(stream);
}
case JfireSE.id_content_un_track ->
{
int classId = stream.readVarInt();
ClassInfo classInfo = getForDeSerialize(classId);
return classInfo.readWithoutTrack(stream);
}
default -> throw new RuntimeException("未知的序列化类型");
}
}
public ClassInfo getForDeSerialize(byte[] classNameBytes, int classId)
{
try
{
Class<?> clazz = Class.forName(new String(classNameBytes, StandardCharsets.UTF_8));
ClassInfo classInfo = getForSerialize(clazz);
if (deSerializedClassInfos == null)
{
deSerializedClassInfos = new ClassInfo[classId + 1];
deSerializedClassInfos[classId] = classInfo;
}
else if (classId >= deSerializedClassInfos.length)
{
int newLen = deSerializedClassInfos.length * 2;
newLen = newLen > classId ? newLen : classId + 1;
ClassInfo[] tmp = new ClassInfo[newLen];
System.arraycopy(deSerializedClassInfos, 0, tmp, 0, deSerializedClassInfos.length);
deSerializedClassInfos = tmp;
deSerializedClassInfos[classId] = classInfo;
}
else
{
deSerializedClassInfos[classId] = classInfo;
}
return classInfo;
}
catch (ClassNotFoundException e)
{
throw new RuntimeException(e);
}
}
public ClassInfo getForDeSerialize(int classId)
{
return deSerializedClassInfos[classId];
}
}

View File

@ -3,20 +3,31 @@ package com.jfirer.se2.classinfo;
import com.jfirer.se2.ByteArray;
import com.jfirer.se2.JfireSE;
import com.jfirer.se2.serializer.Serializer;
import io.github.karlatemp.unsafeaccessor.Unsafe;
import lombok.Data;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
@Data
public abstract class ClassInfo
{
protected final short classId;
protected final String className;
protected final Class<?> clazz;
protected final boolean refTrack;
protected Object[] tracking;
protected int refTrackingIndex = 0;
protected Serializer serializer;
protected final short classId;
protected final byte[] classNameBytes;
protected final Class<?> clazz;
protected final boolean refTrack;
protected Object[] tracking;
protected int refTrackingIndex = 0;
protected Serializer serializer;
protected static final Unsafe UNSAFE = Unsafe.getUnsafe();
public ClassInfo(short classId, Class<?> clazz, boolean refTrack)
{
this.classId = classId;
this.clazz = clazz;
this.refTrack = refTrack;
classNameBytes = clazz.getName().getBytes(StandardCharsets.UTF_8);
}
public int addTracking(Object instance)
{
@ -75,5 +86,43 @@ public abstract class ClassInfo
}
}
public abstract void readWithTrack(ByteArray byteArray);
/**
*
*
* @param byteArray
* @return
*/
public Object readWithTrack(ByteArray byteArray)
{
try
{
Object instance = UNSAFE.allocateInstance(clazz);
addTracking(instance);
serializer.read(byteArray, instance);
return instance;
}
catch (InstantiationException e)
{
throw new RuntimeException(e);
}
}
public Object readWithoutTrack(ByteArray byteArray)
{
try
{
Object instance = UNSAFE.allocateInstance(clazz);
serializer.read(byteArray, instance);
return instance;
}
catch (InstantiationException e)
{
throw new RuntimeException(e);
}
}
public Object getInstanceById(int instanceId)
{
return tracking[instanceId];
}
}

View File

@ -16,9 +16,9 @@ public class DynamicClassInfo extends ClassInfo
*/
private boolean firstSerialized = true;
public DynamicClassInfo(short classId, String className, Class<?> clazz, boolean refTracking)
public DynamicClassInfo(short classId, Class<?> clazz, boolean refTracking)
{
super(classId, className, clazz, refTracking);
super(classId, clazz, refTracking);
}
@Override
@ -38,7 +38,7 @@ public class DynamicClassInfo extends ClassInfo
firstSerialized = true;
addTracking(instance);
byteArray.put(JfireSE.NAME_ID_CONTENT_TRACK);
byteArray.writeString(className);
byteArray.writeBytesWithSizeEmbedded(classNameBytes);
byteArray.writeVarInt(classId);
serializer.writeBytes(byteArray, instance);
}
@ -65,7 +65,7 @@ public class DynamicClassInfo extends ClassInfo
{
firstSerialized = true;
byteArray.put(JfireSE.NAME_ID_CONTENT_UN_TRACK);
byteArray.writeString(className);
byteArray.writeBytesWithSizeEmbedded(classNameBytes);
byteArray.writeVarInt(classId);
serializer.writeBytes(byteArray, instance);
}

View File

@ -5,13 +5,13 @@ import com.jfirer.se2.JfireSE;
public class StaticClasInfo extends ClassInfo
{
public StaticClasInfo(short classId, String className, Class<?> clazz, boolean refTracking)
public StaticClasInfo(short classId, Class<?> clazz, boolean refTracking)
{
super(classId, className, clazz, refTracking);
super(classId, clazz, refTracking);
}
@Override
public void write(ByteArray byteArray, Object instance)
public void write(ByteArray byteArray, Object instance)
{
if (refTrack)
{
@ -36,4 +36,10 @@ public class StaticClasInfo extends ClassInfo
serializer.writeBytes(byteArray, instance);
}
}
@Override
public Object readWithTrack(ByteArray byteArray)
{
return null;
}
}

View File

@ -6,5 +6,7 @@ public interface Serializer
{
void writeBytes(ByteArray byteArray, Object instance);
Object read(ByteArray stream);
void read(ByteArray stream, Object instance);
}

View File

@ -12,6 +12,9 @@ public class SerializerFactory
public Serializer getSerializer(Class<?> clazz, JfireSEImpl jfireSE)
{
return store.putIfAbsent(clazz, new ObjectSerializer(clazz, jfireSE));
// ObjectSerializer objectSerializer = new ObjectSerializer(clazz, jfireSE);
Serializer objectSerializer = ObjectSerializer.buildCompileVersion(clazz, jfireSE);
store.putIfAbsent(clazz, objectSerializer);
return objectSerializer;
}
}

View File

@ -1,7 +1,6 @@
package com.jfirer.se2.serializer.impl.ObjectSerializer;
import com.jfirer.baseutil.reflect.ReflectUtil;
import com.jfirer.baseutil.reflect.ValueAccessor;
import com.jfirer.se2.ByteArray;
import com.jfirer.se2.JfireSE;
@ -11,7 +10,7 @@ public class BoxedFieldInfo extends FieldInfo
{
public BoxedFieldInfo(Field field)
{
super(ReflectUtil.getClassId(field.getType()), new ValueAccessor(field));
super(field);
}
@Override
@ -139,4 +138,77 @@ public class BoxedFieldInfo extends FieldInfo
default -> throw new RuntimeException("不支持的类型");
}
}
@Override
public void read(ByteArray byteArray, Object instance)
{
boolean exist = byteArray.get() == JfireSE.NOT_NULL;
switch (classId)
{
case ReflectUtil.CLASS_BOOL ->
{
if (exist)
{
accessor.setObject(instance, byteArray.readBoolean());
}
}
case ReflectUtil.CLASS_BYTE ->
{
if (exist)
{
accessor.setObject(instance, byteArray.get());
}
}
case ReflectUtil.CLASS_CHAR ->
{
if (exist)
{
accessor.setObject(instance, byteArray.readChar());
}
}
case ReflectUtil.CLASS_SHORT ->
{
if (exist)
{
accessor.setObject(instance, (short) byteArray.readVarInt());
}
}
case ReflectUtil.CLASS_INT ->
{
if (exist)
{
accessor.setObject(instance, byteArray.readVarInt());
}
}
case ReflectUtil.CLASS_LONG ->
{
if (exist)
{
accessor.setObject(instance, byteArray.readVarLong());
}
}
case ReflectUtil.CLASS_FLOAT ->
{
if (exist)
{
accessor.setObject(instance, byteArray.readFloat());
}
}
case ReflectUtil.CLASS_DOUBLE ->
{
if (exist)
{
accessor.setObject(instance, byteArray.readDouble());
}
}
case ReflectUtil.CLASS_STRING ->
{
if (exist)
{
accessor.setObject(instance, byteArray.readString());
}
}
default -> throw new RuntimeException("不支持的类型");
}
}
}

View File

@ -1,18 +1,27 @@
package com.jfirer.se2.serializer.impl.ObjectSerializer;
import com.jfirer.baseutil.reflect.ReflectUtil;
import com.jfirer.baseutil.reflect.ValueAccessor;
import com.jfirer.baseutil.smc.compiler.CompileHelper;
import com.jfirer.se2.ByteArray;
import java.lang.reflect.Field;
public abstract class FieldInfo
{
protected int classId;
protected ValueAccessor accessor;
protected final int classId;
protected final ValueAccessor accessor;
private static final CompileHelper COMPILE_HELPER = new CompileHelper();
protected Field field;
public FieldInfo(int classId, ValueAccessor accessor)
public FieldInfo(Field field)
{
this.classId = classId;
this.accessor = accessor;
this.classId = ReflectUtil.getClassId(field.getType());
this.accessor = new ValueAccessor(field);
this.field = field;
}
public abstract void write(ByteArray byteArray, Object instance);
public abstract void read(ByteArray byteArray, Object instance);
}

View File

@ -1,7 +1,5 @@
package com.jfirer.se2.serializer.impl.ObjectSerializer;
import com.jfirer.baseutil.reflect.ReflectUtil;
import com.jfirer.baseutil.reflect.ValueAccessor;
import com.jfirer.se2.ByteArray;
import com.jfirer.se2.JfireSE;
import com.jfirer.se2.JfireSEImpl;
@ -11,12 +9,14 @@ import java.lang.reflect.Field;
public class FinalFieldInfo extends FieldInfo
{
private ClassInfo classInfo;
private ClassInfo classInfo;
private JfireSEImpl jfireSE;
public FinalFieldInfo(Field field, JfireSEImpl jfireSE)
{
super(ReflectUtil.getClassId(field.getType()), new ValueAccessor(field));
classInfo = jfireSE.getForSerialize(field.getType());
super(field);
classInfo = jfireSE.getForSerialize(field.getType());
this.jfireSE = jfireSE;
}
@Override
@ -32,4 +32,37 @@ public class FinalFieldInfo extends FieldInfo
classInfo.writeKnownClazz(byteArray, obj);
}
}
@Override
public void read(ByteArray byteArray, Object instance)
{
byte flag = byteArray.get();
if (flag == JfireSE.NULL)
{
accessor.setObject(instance, null);
}
else
{
switch (flag)
{
case JfireSE.instance_id ->
{
int instanceId = byteArray.readVarInt();
Object property = classInfo.getInstanceById(instanceId);
accessor.setObject(instance, property);
}
case JfireSE.content_track ->
{
Object property = classInfo.readWithTrack(byteArray);
accessor.setObject(instance, property);
}
case JfireSE.content_un_track ->
{
Object property = classInfo.readWithoutTrack(byteArray);
accessor.setObject(instance, property);
}
default -> throw new RuntimeException("flag:" + flag);
}
}
}
}

View File

@ -1,21 +1,54 @@
package com.jfirer.se2.serializer.impl.ObjectSerializer;
import com.jfirer.baseutil.reflect.ReflectUtil;
import com.jfirer.baseutil.smc.compiler.CompileHelper;
import com.jfirer.baseutil.smc.model.ClassModel;
import com.jfirer.baseutil.smc.model.ConstructorModel;
import com.jfirer.baseutil.smc.model.FieldModel;
import com.jfirer.baseutil.smc.model.MethodModel;
import com.jfirer.se2.ByteArray;
import com.jfirer.se2.JfireSEImpl;
import com.jfirer.se2.serializer.Serializer;
import io.github.karlatemp.unsafeaccessor.Unsafe;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.function.Predicate;
public class ObjectSerializer implements Serializer
{
private Class<?> clazz;
private FieldInfo[] fieldInfos;
private Class<?> clazz;
private FieldInfo[] fieldInfos;
static int COMPILE_COUNT = 1;
private static final Unsafe UNSAFE = Unsafe.getUnsafe();
public ObjectSerializer(Class<?> clazz, JfireSEImpl jfireSE)
{
fieldInfos = parse(clazz, jfireSE).toArray(FieldInfo[]::new);
}
@Override
public void writeBytes(ByteArray byteArray, Object instance)
{
for (FieldInfo each : fieldInfos)
{
each.write(byteArray, instance);
}
}
@Override
public void read(ByteArray stream, Object instance)
{
for (FieldInfo each : fieldInfos)
{
each.read(stream, instance);
}
}
public static List<FieldInfo> parse(Class<?> clazz, JfireSEImpl jfireSE)
{
Class type = clazz;
List<Field> fields = new ArrayList<>();
@ -53,15 +86,159 @@ public class ObjectSerializer implements Serializer
list.addAll(boxedFieldInfos);
list.addAll(finalFieldInfos);
list.addAll(variableFieldInfos);
fieldInfos = list.toArray(FieldInfo[]::new);
return list;
}
@Override
public void writeBytes(ByteArray byteArray, Object instance)
public static Serializer buildCompileVersion(Class<?> clazz, JfireSEImpl jfireSE)
{
for (FieldInfo each : fieldInfos)
List<FieldInfo> parse = parse(clazz, jfireSE);
ClassModel classModel = new ClassModel("ObjectSerializer_compile_" + COMPILE_COUNT);
COMPILE_COUNT++;
classModel.addInterface(Serializer.class);
classModel.addImport(Unsafe.class);
classModel.addImport(List.class);
classModel.addImport(FieldInfo.class);
classModel.addImport(ByteArray.class);
classModel.addField(new FieldModel("UNSAFE", Unsafe.class, "Unsafe.getUnsafe()", classModel));
ConstructorModel constructorModel = new ConstructorModel(classModel);
constructorModel.setParamTypes(Class.class, JfireSEImpl.class, List.class);
constructorModel.setParamNames("clazz", "jfireSE", "list");
StringBuilder constructorBody = new StringBuilder();
try
{
each.write(byteArray, instance);
MethodModel writeMethod = new MethodModel(Serializer.class.getDeclaredMethod("writeBytes", ByteArray.class, Object.class), classModel);
writeMethod.setParamterNames("byteArray", "instance");
StringBuilder writeBody = new StringBuilder();
MethodModel readMethod = new MethodModel(Serializer.class.getDeclaredMethod("read", ByteArray.class, Object.class), classModel);
readMethod.setParamterNames("byteArray", "instance");
StringBuilder readBody = new StringBuilder();
int fieldIndex = 0;
for (FieldInfo fieldInfo : parse)
{
long l = UNSAFE.objectFieldOffset(fieldInfo.field);
if (fieldInfo instanceof PrimitiveFieldInfo primitiveFieldInfo)
{
switch (fieldInfo.classId)
{
case ReflectUtil.PRIMITIVE_BYTE ->
{
writeBody.append("byteArray.put(UNSAFE.getByte(instance, " + l + "));\r\n");
readBody.append("UNSAFE.putByte(instance," + l + ", byteArray.get());\r\n");
}
case ReflectUtil.PRIMITIVE_INT ->
{
writeBody.append("byteArray.writeVarInt(UNSAFE.getInt(instance, " + l + "));\r\n");
readBody.append("UNSAFE.putInt(instance," + l + ", byteArray.readVarInt());\r\n");
}
case ReflectUtil.PRIMITIVE_SHORT ->
{
writeBody.append("byteArray.writeVarInt(UNSAFE.getShort(instance, " + l + "));\r\n");
readBody.append("UNSAFE.putShort(instance," + l + ", (short) byteArray.readVarInt());\r\n");
}
case ReflectUtil.PRIMITIVE_LONG ->
{
writeBody.append("byteArray.writeVarLong(UNSAFE.getLong(instance, " + l + "));\r\n");
readBody.append("UNSAFE.putLong(instance," + l + ", byteArray.readVarLong());\r\n");
}
case ReflectUtil.PRIMITIVE_FLOAT ->
{
writeBody.append("byteArray.writeFloat(UNSAFE.getFloat(instance, " + l + "));\r\n");
readBody.append("UNSAFE.putFloat(instance," + l + ", byteArray.readFloat());\r\n");
}
case ReflectUtil.PRIMITIVE_DOUBLE ->
{
writeBody.append("byteArray.writeDouble(UNSAFE.getDouble(instance, " + l + "));\r\n");
readBody.append("UNSAFE.putDouble(instance," + l + ", byteArray.readDouble());\r\n");
}
case ReflectUtil.PRIMITIVE_BOOL ->
{
writeBody.append("byteArray.writeBoolean(UNSAFE.getBoolean(instance, " + l + "));\r\n");
readBody.append("UNSAFE.putBoolean(instance," + l + ", byteArray.readBoolean());\r\n");
}
case ReflectUtil.PRIMITIVE_CHAR ->
{
writeBody.append("byteArray.writeChar(UNSAFE.getChar(instance, " + l + "));\r\n");
readBody.append("UNSAFE.putChar(instance," + l + ", byteArray.readChar());\r\n");
}
default -> throw new RuntimeException("不支持的类型");
}
}
else if (fieldInfo instanceof BoxedFieldInfo boxedFieldInfo)
{
switch (fieldInfo.classId)
{
case ReflectUtil.PRIMITIVE_BYTE ->
{
writeBody.append("byteArray.writeByte((Byte) UNSAFE.getObject(instance, " + l + "));\r\n");
readBody.append("UNSAFE.putObject(instance," + l + ", byteArray.readByte());\r\n");
}
case ReflectUtil.PRIMITIVE_INT ->
{
writeBody.append("byteArray.writeVarInt((Integer) UNSAFE.getObject(instance, " + l + "));\r\n");
readBody.append("UNSAFE.putObject(instance," + l + ", byteArray.readVarInt());\r\n");
}
case ReflectUtil.PRIMITIVE_SHORT ->
{
writeBody.append("byteArray.writeVarInt((Short) UNSAFE.getObject(instance, " + l + "));\r\n");
readBody.append("UNSAFE.putObject(instance," + l + ", (short) byteArray.readVarInt());\r\n");
}
case ReflectUtil.PRIMITIVE_LONG ->
{
writeBody.append("byteArray.writeVarLong((Long) UNSAFE.getObject(instance, " + l + "));\r\n");
readBody.append("UNSAFE.putObject(instance," + l + ", byteArray.readVarLong());\r\n");
}
case ReflectUtil.PRIMITIVE_FLOAT ->
{
writeBody.append("byteArray.writeFloat((Float) UNSAFE.getObject(instance, " + l + "));\r\n");
readBody.append("UNSAFE.putObject(instance," + l + ", byteArray.readFloat());");
}
case ReflectUtil.PRIMITIVE_DOUBLE ->
{
writeBody.append("byteArray.writeDouble((Double) UNSAFE.getObject(instance, " + l + "));\r\n");
readBody.append("UNSAFE.putObject(instance," + l + ", byteArray.readDouble());\r\n");
}
case ReflectUtil.PRIMITIVE_BOOL ->
{
writeBody.append("byteArray.writeBoolean((Boolean) UNSAFE.getObject(instance, " + l + "));\r\n");
readBody.append("UNSAFE.putObject(instance," + l + ", byteArray.readBoolean());\r\n");
}
case ReflectUtil.PRIMITIVE_CHAR ->
{
writeBody.append("byteArray.writeChar((Character) UNSAFE.getObject(instance, " + l + "));\r\n");
readBody.append("UNSAFE.putObject(instance," + l + ", byteArray.readChar());\r\n");
}
case ReflectUtil.CLASS_STRING ->
{
writeBody.append("byteArray.writeString((String) UNSAFE.getObject(instance, " + l + "));\r\n");
readBody.append("UNSAFE.putObject(instance," + l + ", byteArray.readString());\r\n");
}
default -> throw new RuntimeException("不支持的类型");
}
}
else if (fieldInfo instanceof VariableFieldInfo || fieldInfo instanceof FinalFieldInfo)
{
FieldModel fieldModel = new FieldModel("fieldInfo_$_" + fieldIndex, VariableFieldInfo.class, classModel);
classModel.addField(fieldModel);
constructorBody.append("fieldInfo_$_" + fieldIndex + "=(FieldInfo)list.get(" + fieldIndex + ");\r\n");
writeBody.append("fieldInfo_$_" + fieldIndex + ".write(byteArray,instance);\r\n");
readBody.append("fieldInfo_$_" + fieldIndex + ".read(byteArray,instance);\r\n");
}
fieldIndex++;
}
constructorModel.setBody(constructorBody.toString());
classModel.addConstructor(constructorModel);
writeMethod.setBody(writeBody.toString());
readMethod.setBody(readBody.toString());
classModel.putMethodModel(writeMethod);
classModel.putMethodModel(readMethod);
CompileHelper compiler = new CompileHelper(Thread.currentThread().getContextClassLoader());
Class<?> compile = compiler.compile(classModel);
Serializer compiledObjectSerializer = (Serializer) compile.getDeclaredConstructor(Class.class, JfireSEImpl.class, List.class).newInstance(clazz, jfireSE, parse);
return compiledObjectSerializer;
}
catch (NoSuchMethodException | IOException | ClassNotFoundException | InstantiationException | IllegalAccessException | InvocationTargetException e)
{
throw new RuntimeException(e);
}
}
}

View File

@ -1,7 +1,6 @@
package com.jfirer.se2.serializer.impl.ObjectSerializer;
import com.jfirer.baseutil.reflect.ReflectUtil;
import com.jfirer.baseutil.reflect.ValueAccessor;
import com.jfirer.se2.ByteArray;
import java.lang.reflect.Field;
@ -10,7 +9,7 @@ public class PrimitiveFieldInfo extends FieldInfo
{
public PrimitiveFieldInfo(Field field)
{
super(ReflectUtil.getClassId(field.getType()), new ValueAccessor(field));
super(field);
}
public void write(ByteArray byteArray, Object instance)
@ -28,4 +27,21 @@ public class PrimitiveFieldInfo extends FieldInfo
default -> throw new RuntimeException("不支持的类型");
}
}
@Override
public void read(ByteArray byteArray, Object instance)
{
switch (classId)
{
case ReflectUtil.PRIMITIVE_BYTE -> accessor.set(instance, byteArray.get());
case ReflectUtil.PRIMITIVE_INT -> accessor.set(instance, byteArray.readVarInt());
case ReflectUtil.PRIMITIVE_SHORT -> accessor.set(instance, (short) byteArray.readVarInt());
case ReflectUtil.PRIMITIVE_LONG -> accessor.set(instance, byteArray.readVarLong());
case ReflectUtil.PRIMITIVE_FLOAT -> accessor.set(instance, byteArray.readFloat());
case ReflectUtil.PRIMITIVE_DOUBLE -> accessor.set(instance, byteArray.readDouble());
case ReflectUtil.PRIMITIVE_BOOL -> accessor.set(instance, byteArray.readBoolean());
case ReflectUtil.PRIMITIVE_CHAR -> accessor.set(instance, byteArray.readChar());
default -> throw new RuntimeException("不支持的类型");
}
}
}

View File

@ -1,7 +1,5 @@
package com.jfirer.se2.serializer.impl.ObjectSerializer;
import com.jfirer.baseutil.reflect.ReflectUtil;
import com.jfirer.baseutil.reflect.ValueAccessor;
import com.jfirer.se2.ByteArray;
import com.jfirer.se2.JfireSE;
import com.jfirer.se2.JfireSEImpl;
@ -17,7 +15,7 @@ public class VariableFieldInfo extends FieldInfo
public VariableFieldInfo(Field field, JfireSEImpl jfireSE)
{
super(ReflectUtil.getClassId(field.getType()), new ValueAccessor(field));
super(field);
classInfo = jfireSE.getForSerialize(field.getType());
this.jfireSE = jfireSE;
if (field.getType().isInterface())
@ -66,4 +64,75 @@ public class VariableFieldInfo extends FieldInfo
}
}
}
@Override
public void read(ByteArray byteArray, Object instance)
{
byte flag = byteArray.get();
if (flag == JfireSE.NULL)
{
accessor.setObject(instance, null);
}
else
{
switch (flag)
{
case JfireSE.NAME_ID_CONTENT_TRACK ->
{
byte[] classNameBytes = byteArray.readBytesWithSizeEmbedded();
int classId = byteArray.readVarInt();
classInfo = jfireSE.getForDeSerialize(classNameBytes, classId);
Object property = classInfo.readWithTrack(byteArray);
accessor.setObject(instance, property);
}
case JfireSE.NAME_ID_CONTENT_UN_TRACK ->
{
byte[] classNameBytes = byteArray.readBytesWithSizeEmbedded();
int classId = byteArray.readVarInt();
classInfo = jfireSE.getForDeSerialize(classNameBytes, classId);
Object property = classInfo.readWithoutTrack(byteArray);
accessor.setObject(instance, property);
}
case JfireSE.ID_INSTANCE_ID ->
{
int classId = byteArray.readVarInt();
int instanceId = byteArray.readVarInt();
classInfo = jfireSE.getForDeSerialize(classId);
Object proeprty = classInfo.getInstanceById(instanceId);
accessor.setObject(instance, proeprty);
}
case JfireSE.id_content_track ->
{
int classId = byteArray.readVarInt();
classInfo = jfireSE.getForDeSerialize(classId);
Object property = classInfo.readWithTrack(byteArray);
accessor.setObject(instance, property);
}
case JfireSE.id_content_un_track ->
{
int classId = byteArray.readVarInt();
classInfo = jfireSE.getForDeSerialize(classId);
Object property = classInfo.readWithoutTrack(byteArray);
accessor.setObject(instance, property);
}
case JfireSE.instance_id ->
{
int instanceId = byteArray.readVarInt();
Object property = firstClassInfo.getInstanceById(instanceId);
accessor.setObject(instance, property);
}
case JfireSE.content_track ->
{
Object property = firstClassInfo.readWithTrack(byteArray);
accessor.setObject(instance, property);
}
case JfireSE.content_un_track ->
{
Object property = firstClassInfo.readWithoutTrack(byteArray);
accessor.setObject(instance, property);
}
default -> throw new RuntimeException("flag:" + flag);
}
}
}
}

View File

@ -14,7 +14,7 @@ import org.openjdk.jmh.runner.options.OptionsBuilder;
import java.util.concurrent.TimeUnit;
@BenchmarkMode(Mode.Throughput)
@Warmup(iterations = 2, time = 1)
@Warmup(iterations = 2, time = 3)
@Measurement(iterations = 3, time = 3)
@OutputTimeUnit(TimeUnit.SECONDS)
@Fork(1)
@ -28,7 +28,7 @@ public class BenchMark
Fury fury = Fury.builder().withLanguage(Language.JAVA)//
.requireClassRegistration(false)//
.withRefTracking(true).build();
JfireSE jfireSE = JfireSE.build();
JfireSE jfireSE = JfireSE.supportRefTracking(true).build();
@Benchmark
public void testNoCompile()

View File

@ -1,12 +1,14 @@
package org.example;
import com.jfirer.se2.ByteArray;
import com.jfirer.se2.JfireSE;
import io.fury.Fury;
import io.fury.config.Language;
import org.junit.Assert;
import org.junit.Test;
public class FunctionTest
{
@Test
public void test()
{
@ -20,4 +22,26 @@ public class FunctionTest
Assert.assertEquals(20, byteArray.readVarInt());
Assert.assertEquals(13453242, byteArray.readVarLong());
}
@Test
public void test2()
{
TestData testData = new TestData();
testData.setB(true);
JfireSE jfireSE = JfireSE.build();
byte[] bytes = jfireSE.write(testData);
Assert.assertEquals(testData, jfireSE.read(bytes));
}
@Test
public void test3()
{
Fury fury = Fury.builder().withLanguage(Language.JAVA)//
.requireClassRegistration(false)//
.withRefTracking(true).build();
TestData data = new TestData();
byte[] serialize = fury.serialize(data);
byte[] serialize1 = fury.serialize(data);
Assert.assertArrayEquals(serialize, serialize1);
}
}

View File

@ -2,20 +2,18 @@ package org.example;
import lombok.Data;
import java.io.Serializable;
@Data
public class TestData implements Serializable
public class TestData
{
private int a = 213212312;
private boolean b = false;
private char c = 'c';
private byte d = 0x11;
private short e = 24;
private long f = 1213124131312321L;
private double g = 231321.2132;
private float h = (float) 4986.2;
private String i = "123452312316789a";
private int a = 213212312;
private boolean b = false;
private char c = 'c';
private byte d = 0x11;
private short e = 24;
private long f = 1213124131312321L;
private double g = 231321.2132;
private float h = (float) 4986.2;
private String i = "123452312316789a";
// private int[] j = new int[]{1, 2, 4, 5};
// private boolean[] k = new boolean[]{true, false, true, false, false, false, true};
// private char[] l = new char[]{'a', 'v', 'q', 'j', 'h', 'e', 'f'};
@ -26,88 +24,5 @@ public class TestData implements Serializable
// private float[] q = new float[]{46486.2f, 49849.2f, 646854.6f};
// private String[] r = new String[]{"abcdf12345", "abdfcgf12323"};
public boolean equals(Object x)
{
if (x instanceof TestData)
{
TestData target = (TestData) x;
// if (target.a == a && target.b == b && target.c == c && target.d == d && target.e == e && target.f == f && target.g == g && target.h == h && target.i.equals(i))
// {
// for (int i = 0; i < target.j.length; i++)
// {
// if (target.j[i] != j[i])
// {
// return false;
// }
// }
// for (int i = 0; i < k.length; i++)
// {
// if (target.k[i] != k[i])
// {
// return false;
// }
// }
// for (int i = 0; i < l.length; i++)
// {
// if (target.l[i] != l[i])
// {
// return false;
// }
// }
// for (int i = 0; i < m.length; i++)
// {
// if (target.m[i] != m[i])
// {
// return false;
// }
// }
// for (int i = 0; i < n.length; i++)
// {
// if (target.n[i] != n[i])
// {
// return false;
// }
// }
// for (int i = 0; i < o.length; i++)
// {
// if (target.o[i] != o[i])
// {
// return false;
// }
// }
// for (int i = 0; i < p.length; i++)
// {
// if (p[i] != target.p[i])
// {
// return false;
// }
// }
// for (int i = 0; i < r.length; i++)
// {
// if (target.r[i].equals(r[i]) == false)
// {
// return false;
// }
// }
// for (int i = 0; i < q.length; i++)
// {
// if (q[i] != target.q[i])
// {
// return false;
// }
// }
// return true;
// }
// else
// {
// return false;
// }
}
else
{
return false;
}
return false;
}
}