java - Vaadin - Tomcat 上的可序列化错误

标签 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 session 持久性的问题。

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

主要问题:

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

最佳答案

前言:此答案假定您的一些序列化/持久化类在部署之间发生变化。

我当然记得第一次使用 Tomcat 遇到这个问题时我挠了挠头。就像您一样,我们也允许为我们的序列化类自动生成 serialVersionUID,这是类成员的某种哈希值。因此,如果这些类以任何方式发生变化,自动生成的 serialVersionUID 也会为它们发生变化。这才是您真正想要的。

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

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

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

关于java - Vaadin - Tomcat 上的可序列化错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33413139/

相关文章:

java - JPA:默认构造函数是否需要为空?

java - AES(Rijndael) 在 Java 8 平台上比 Blowfish 快吗?

spring - Tomcat 7 中的 CSRF 保护

java - 如何在tomcat中运行使用高内存的超长请求?

browser - SWT 浏览器组件阻止 SWT UI 线程

java - vaadin 表单无法隐藏空字段

java - 使用 SharedPreferences 在 Android 中实现 Collection 夹列表

java - 为什么我应该将实现的接口(interface)方法声明为 "public"?

apache - mod_proxy 可以处理带参数的 GET 响应(使用 tomcat 作为后端)

java - Vaadin 7 和 org.vaadin.addon.customfield。包裹