背景
关于序列化貌似很久前写过一篇关于Object的 由于某些原因一直没有写完(好吧,承认年纪大了,老是忘)
还有关于dubbo使用hessianDubbo序列化之hessian2
现在的情况是大部分情况下Java默认序列化都是系统中拖后腿的组件,因此dubbo默认就采用了hessian2 (有坑),sad 我们在dubbo中仍然采用了java默认的序列化方式
序列化框架性能对比(kryo、hessian、java、protostuff)
简介:
| 优点 | 缺点 |
Kryo | 速度快,序列化后体积小 | 跨语言支持较复杂 |
Hessian | 默认支持跨语言 | 较慢 |
Protostuff | 速度快,基于protobuf | 需静态编译 |
Protostuff-Runtime | 无需静态编译,但序列化前需预先传入schema | 不支持无默认构造函数的类,反序列化时需用户自己初始化序列化后的对象,其只负责将该对象进行赋值 |
Java | 使用方便,可序列化所有类 | 速度慢,占空间 |
几个常见的比较如上
我们在J2cache中选用了Fst作为序列化框架
问题
为啥一段时间类经常出现如下报错
2017-08-16 09:49:00,058 [ERROR] [RMI TCP Connection(9713)-114.55.25.15] n.o.j.r.RedisCache:109 Error occured when get data from redis2 cache java.io.IOException: java.lang.RuntimeException: class not found CLASSNAME: loader:WebappClassLoader context: /kzf6 delegate: false repositories: /WEB-INF/classes/ ----------> Parent Classloader: java.net.URLClassLoader@183648b1 at org.nustaq.serialization.FSTObjectInput.readObject(FSTObjectInput.java:243) at net.oschina.j2cache.util.FSTSerializer.deserialize(FSTSerializer.java:50) at net.oschina.j2cache.util.SerializationUtils.deserialize(SerializationUtils.java:66) at net.oschina.j2cache.redis.RedisCache.get(RedisCache.java:82) at net.oschina.j2cache.CacheManager.get(CacheManager.java:101) at net.oschina.j2cache.RedisCacheChannel.get(RedisCacheChannel.java:78) at org.nutz.j2cache.spring.SpringJ2Cache.get(SpringJ2Cache.java:29) at org.springframework.cache.interceptor.CacheAspectSupport.inspectCacheables(CacheAspectSupport.java:294) at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:199) at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:66) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:96) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:91) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:80) at com.air.tqb.spring.aop.ExceptionHandlerAspect.handleException(ExceptionHandlerAspect.java:48) at sun.reflect.GeneratedMethodAccessor243.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:621) at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:610) at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:65) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:633) at com.air.tqb.service.base.impl.OrganizationServiceImpl$$EnhancerBySpringCGLIB$$f5a41e99.getMainBranchByOrgId(<generated>) at com.air.tqb.service.base.impl.PartInfoServiceImpl.addTmPartInfo(PartInfoServiceImpl.java:162) at com.air.tqb.service.base.impl.PartInfoServiceImpl$$FastClassBySpringCGLIB$$2964f90.invoke(<generated>) at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:700) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:51) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.aspectj.AspectJAfterAdvice.invoke(AspectJAfterAdvice.java:42) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:96) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:91) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:80) at com.air.tqb.spring.aop.ExceptionHandlerAspect.handleException(ExceptionHandlerAspect.java:48) at sun.reflect.GeneratedMethodAccessor243.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:621) at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:610) at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:65) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:633) at com.air.tqb.service.base.impl.PartInfoServiceImpl$$EnhancerBySpringCGLIB$$e113147c.addTmPartInfo(<generated>) at com.air.tqb.service.base.impl.PubMdmPartServiceImpl.mdmPartHandler(PubMdmPartServiceImpl.java:46) at com.air.tqb.service.base.impl.PubMdmPartServiceImpl$$FastClassBySpringCGLIB$$8fa955e5.invoke(<generated>) at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:700) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:96) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:91) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:80) at com.air.tqb.spring.aop.ExceptionHandlerAspect.handleException(ExceptionHandlerAspect.java:48) at sun.reflect.GeneratedMethodAccessor243.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:621) at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:610) at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:65) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:633) at com.air.tqb.service.base.impl.PubMdmPartServiceImpl$$EnhancerBySpringCGLIB$$2d5a6dc9.mdmPartHandler(<generated>) at com.air.tqb.service.stock.impl.PurchaseServiceImpl.addPurchase(PurchaseServiceImpl.java:373) at com.air.tqb.service.stock.impl.PurchaseServiceImpl.addPurchase(PurchaseServiceImpl.java:423) at com.air.tqb.service.stock.impl.PurchaseServiceImpl$$FastClassBySpringCGLIB$$c35907b1.invoke(<generated>) at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:700) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:51) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.aspectj.AspectJAfterAdvice.invoke(AspectJAfterAdvice.java:42) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:96) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:80) at com.air.tqb.aop.SecurityAspect.securityLog(SecurityAspect.java:37) at sun.reflect.GeneratedMethodAccessor1371.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:621) at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:610) at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:65) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:161) at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:91) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:80) at com.air.tqb.spring.aop.ExceptionHandlerAspect.handleException(ExceptionHandlerAspect.java:48) at sun.reflect.GeneratedMethodAccessor243.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:621) at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:610) at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:65) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:633) at com.air.tqb.service.stock.impl.PurchaseServiceImpl$$EnhancerBySpringCGLIB$$365fb830.addPurchase(<generated>) at com.air.tqb.rmi.impl.SupplyChainRmiImpl.createPurchase(SupplyChainRmiImpl.java:588) at com.air.tqb.rmi.impl.SupplyChainRmiImpl.addPurchase(SupplyChainRmiImpl.java:254) at com.air.tqb.rmi.impl.SupplyChainRmiImpl$$FastClassBySpringCGLIB$$2084dc30.invoke(<generated>) at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:700) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:91) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:633) at com.air.tqb.rmi.impl.SupplyChainRmiImpl$$EnhancerBySpringCGLIB$$593bb1aa.addPurchase(<generated>) at sun.reflect.GeneratedMethodAccessor7577.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) at org.springframework.remoting.support.RemoteInvocationTraceInterceptor.invoke(RemoteInvocationTraceInterceptor.java:77) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204) at com.sun.proxy.$Proxy179.addPurchase(Unknown Source) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.springframework.remoting.support.RemoteInvocation.invoke(RemoteInvocation.java:205) at org.springframework.remoting.support.DefaultRemoteInvocationExecutor.invoke(DefaultRemoteInvocationExecutor.java:38) at com.air.tqb.rmi.clientInfo.ClientInfoRemoteInvocationExecutor.invoke(ClientInfoRemoteInvocationExecutor.java:26) at org.springframework.remoting.support.RemoteInvocationBasedExporter.invoke(RemoteInvocationBasedExporter.java:78) at org.springframework.remoting.rmi.RmiBasedExporter.invoke(RmiBasedExporter.java:73) at org.springframework.remoting.rmi.RmiInvocationWrapper.invoke(RmiInvocationWrapper.java:72) at sun.reflect.GeneratedMethodAccessor3254.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:322) at sun.rmi.transport.Transport$2.run(Transport.java:202) at sun.rmi.transport.Transport$2.run(Transport.java:199) at java.security.AccessController.doPrivileged(Native Method) at sun.rmi.transport.Transport.serviceCall(Transport.java:198) at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:567) at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:828) at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.access$400(TCPTransport.java:619) at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$1.run(TCPTransport.java:684) at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$1.run(TCPTransport.java:681) at java.security.AccessController.doPrivileged(Native Method) at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:681) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:745) Caused by: java.lang.RuntimeException: class not found CLASSNAME: loader:WebappClassLoader context: /kzf6 delegate: false repositories: /WEB-INF/classes/ ----------> Parent Classloader: java.net.URLClassLoader@183648b1 at org.nustaq.serialization.FSTClazzNameRegistry.classForName(FSTClazzNameRegistry.java:234) at org.nustaq.serialization.FSTClazzNameRegistry.classForName(FSTClazzNameRegistry.java:189) at org.nustaq.serialization.FSTClazzNameRegistry.decodeClass(FSTClazzNameRegistry.java:172) at org.nustaq.serialization.coders.FSTStreamDecoder.readClass(FSTStreamDecoder.java:472) at org.nustaq.serialization.FSTObjectInput.readClass(FSTObjectInput.java:925) at org.nustaq.serialization.FSTObjectInput.readObjectWithHeader(FSTObjectInput.java:343) at org.nustaq.serialization.FSTObjectInput.readObjectFields(FSTObjectInput.java:701) at org.nustaq.serialization.FSTObjectInput.instantiateAndReadNoSer(FSTObjectInput.java:555) at org.nustaq.serialization.FSTObjectInput.readObjectWithHeader(FSTObjectInput.java:370) at org.nustaq.serialization.FSTObjectInput.readObjectFields(FSTObjectInput.java:701) at org.nustaq.serialization.FSTObjectInput.instantiateAndReadNoSer(FSTObjectInput.java:555) at org.nustaq.serialization.FSTObjectInput.readObjectWithHeader(FSTObjectInput.java:370) at org.nustaq.serialization.FSTObjectInput.readObjectInternal(FSTObjectInput.java:327) at org.nustaq.serialization.FSTObjectInput.readObject(FSTObjectInput.java:307) at org.nustaq.serialization.FSTObjectInput.readObject(FSTObjectInput.java:241) ... 159 common frames omitted Caused by: java.lang.ClassNotFoundException: at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:278) at org.nustaq.serialization.FSTClazzNameRegistry.classForName(FSTClazzNameRegistry.java:196) ... 173 common frames omitted
大概看了一下报错报的比较奇怪,这个class 不存在(空)
结论
fst在做反序列化时 由于该数据原先序列化的时候类(可以称之为模板)是有10个字段,但是当开发增加了2个字段后 由于既存的数据中已经均是10个字段的数据(实例)
但是事实上新的版本中已经变成12个字段了。
当做反序列化时由于根据对应的class信息(没有指定version annotation)导致反序列化报错
查看FST说明如下
@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD}) /** * support for adding fields without breaking compatibility to old streams. * For each release of your app increment the version value. No Version annotation means version=0. * Note that each added field needs to be annotated. * * e.g. * * class MyClass implements Serializable { * * // fields on initial release 1.0 * int x; * String y; * * // fields added with release 1.5 * @Version(1) String added; * @Version(1) String alsoAdded; * * // fields added with release 2.0 * @Version(2) String addedv2; * @Version(2) String alsoAddedv2; * * } * * If an old class is read, new fields will be set to default values. You can register a VersionConflictListener * at FSTObjectInput in order to fill in defaults for new fields. * * Notes/Limits: * - Removing fields will break backward compatibility. You can only Add new fields. * - Can slow down serialization over time (if many versions) * - does not work for Externalizable or Classes which make use of JDK-special features such as readObject/writeObject * (AKA does not work if fst has to fall back to 'compatible mode' for an object). * - in case you use custom serializers, your custom serializer has to handle versioning * */ public @interface Version { byte value(); }
要求必须指定version,如果有需要设置默认值等等可以使用VersionConflictListener
那么解决方案也很简单,当增加字段的时候直接将缓存清空即可(避免增加version字段) mac环境下ehcache 广播rmi异常解决&JMX相关