Vaadin - Tomcat上的可序列化错误

时间:2015-10-29 11:35:35

标签: java tomcat vaadin

我的示例应用配置:Java 8,Vaadin 7.5.6; 在Apache Tomcat 8.0.24上部署。

重新部署后不时,我在服务器启动时获得了一些例外。例如今天在启动时:

2015-10-29 09:54:15 ERROR StandardManager - standardManager.loading.ioe
java.io.InvalidClassException: com.vaadin.server.WebBrowser; local class incompatible: stream classdesc serialVersionUID = -4707470459521903161, local class serialVersionUID = 1931594131304735556
        at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:621) ~[?:1.8.0_51]
        at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1623) ~[?:1.8.0_51]
        at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1518) ~[?:1.8.0_51]
        at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1774) ~[?:1.8.0_51]
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351) ~[?:1.8.0_51]
        at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2000) ~[?:1.8.0_51]
        at java.io.ObjectInputStream.defaultReadObject(ObjectInputStream.java:501) ~[?:1.8.0_51]
        at com.vaadin.server.VaadinSession.readObject(VaadinSession.java:1443) ~[vaadin-server-7.5.6.jar:?]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_51]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_51]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_51]
        at java.lang.reflect.Method.invoke(Method.java:497) ~[?:1.8.0_51]
        at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1017) ~[?:1.8.0_51]
        at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1900) ~[?:1.8.0_51]
        at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801) ~[?:1.8.0_51]
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351) ~[?:1.8.0_51]
        at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371) ~[?:1.8.0_51]
        at org.apache.catalina.session.StandardSession.doReadObject(StandardSession.java:1634) ~[catalina.jar:8.0.24]
        at org.apache.catalina.session.StandardSession.readObjectData(StandardSession.java:1099) ~[catalina.jar:8.0.24]
        at org.apache.catalina.session.StandardManager.doLoad(StandardManager.java:261) [catalina.jar:8.0.24]
        at org.apache.catalina.session.StandardManager.load(StandardManager.java:180) [catalina.jar:8.0.24]
        at org.apache.catalina.session.StandardManager.startInternal(StandardManager.java:460) [catalina.jar:8.0.24]
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) [catalina.jar:8.0.24]
        at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5184) [catalina.jar:8.0.24]
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) [catalina.jar:8.0.24]
        at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:725) [catalina.jar:8.0.24]
        at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:701) [catalina.jar:8.0.24]
        at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:717) [catalina.jar:8.0.24]
        at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:945) [catalina.jar:8.0.24]
        at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1768) [catalina.jar:8.0.24]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [?:1.8.0_51]
        at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:1.8.0_51]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [?:1.8.0_51]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [?:1.8.0_51]
        at java.lang.Thread.run(Thread.java:745) [?:1.8.0_51]
2015-10-29 09:54:15 ERROR StandardManager - Exception loading sessions from persistent storage
java.io.InvalidClassException: com.vaadin.server.WebBrowser; local class incompatible: stream classdesc serialVersionUID = -4707470459521903161, local class serialVersionUID = 1931594131304735556
        at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:621) ~[?:1.8.0_51]
        at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1623) ~[?:1.8.0_51]
        at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1518) ~[?:1.8.0_51]
        at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1774) ~[?:1.8.0_51]
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351) ~[?:1.8.0_51]
        at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2000) ~[?:1.8.0_51]
        at java.io.ObjectInputStream.defaultReadObject(ObjectInputStream.java:501) ~[?:1.8.0_51]
        at com.vaadin.server.VaadinSession.readObject(VaadinSession.java:1443) ~[vaadin-server-7.5.6.jar:?]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_51]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_51]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_51]
        at java.lang.reflect.Method.invoke(Method.java:497) ~[?:1.8.0_51]
        at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1017) ~[?:1.8.0_51]
        at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1900) ~[?:1.8.0_51]
        at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801) ~[?:1.8.0_51]
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351) ~[?:1.8.0_51]
        at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371) ~[?:1.8.0_51]
        at org.apache.catalina.session.StandardSession.doReadObject(StandardSession.java:1634) ~[catalina.jar:8.0.24]
        at org.apache.catalina.session.StandardSession.readObjectData(StandardSession.java:1099) ~[catalina.jar:8.0.24]
        at org.apache.catalina.session.StandardManager.doLoad(StandardManager.java:261) ~[catalina.jar:8.0.24]
        at org.apache.catalina.session.StandardManager.load(StandardManager.java:180) ~[catalina.jar:8.0.24]
        at org.apache.catalina.session.StandardManager.startInternal(StandardManager.java:460) [catalina.jar:8.0.24]
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) [catalina.jar:8.0.24]
        at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5184) [catalina.jar:8.0.24]
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) [catalina.jar:8.0.24]
        at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:725) [catalina.jar:8.0.24]
        at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:701) [catalina.jar:8.0.24]
        at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:717) [catalina.jar:8.0.24]
        at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:945) [catalina.jar:8.0.24]
        at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1768) [catalina.jar:8.0.24]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [?:1.8.0_51]
        at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:1.8.0_51]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [?:1.8.0_51]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [?:1.8.0_51]
        at java.lang.Thread.run(Thread.java:745) [?:1.8.0_51]

第二次启动后一切都很好 - 没有错误。实际上我找到了solution on SO - 这是重启后Tomcat会话持久性的问题。

但我查看了WebBrowser代码,实际上没有serialVersionUID变量,即使这个类实现了Serializable。当然它可以工作,因为这个变量是generated using hash function。但这是第一个小问题:这是真的正确还是一种错误?

主要问题:

假设使用Vaadin,如何防止此类异常?我应该禁用Tomcat会话持久性还是应该在代码中搜索一些错误/问题?

1 个答案:

答案 0 :(得分:1)

前言:这个答案假设您的某些序列化/持久化的类在部署之间发生了变化。

我当然记得第一次遇到Tomcat时我挠头。就像你一样,我们也允许为我们的序列化类自动生成serialVersionUID,这是类的成员的某种哈希。因此,如果这些类以任何方式发生更改,则自动生成的serialVersionUID将针对它们进行更改。这真的是你想要的。

所以简而言之,系统正在做它应该做的事情(根本不是一个错误)。对象的持久化序列化版本与新部署中的类不匹配 - 因此在尝试反序列化时会出现异常。然后它们被消耗/丢弃,这就是它在第二次重启时工作的原因。

一个有点残酷的部署策略可能是在部署新战争之前销毁Tomcat下的工作\ Catalina \ localhost \ yourapplicationname目录。如果在Tomcat下运行其他应用程序,则销毁整个工作目录将是一种反社会行为:)

当然,您可以尝试添加对反序列化多个"版本的支持。对象,但这将非常非常难以维护。