【问题标题】:Cannot serialize into L2 cache无法序列化到 L2 缓存中
【发布时间】:2018-03-13 20:02:12
【问题描述】:

我在一个独立的 Java Web 应用程序(它使用 Jetty、Servlets [是的,架构有点旧] 和 spring)中使用 datanucleus 和 JDO 时遇到了某种错误配置。

我们目前正在开发一个新版本;原始项目在过去 3 年内没有任何依赖更新;所以我们想要进行那些不错的安全性、性能和功能升级,但正如预期的那样,升级并不那么容易。

我们已经解决了大部分问题,但变得非常乏味的问题还没有:

  • 服务器启动时,检查数据库中是否有默认用户;这是蒙戈。如果没有用户,则创建默认用户。在任何情况下,服务器都会启动。

我们正在使用datanucleus + JDO来访问底层数据库;主要是因为它已经存在并且因为系统的大部分真的都与它相关联。到目前为止,我们可以确认 datanucleus 可以读取数据库(调试器显示来自数据库的非空结果,它正确地代表了默认用户;以及来自活动端点的一些其他虚拟结果)。但是当 datanucleus 试图缓存结果时,它就陷入了死胡同。

错误堆栈如下:

GRAVE: exception catched
javax.jdo.JDOException: Failed to set object CachedPC : cls=mobi.allshoppings.model.User version=null loadedFlags=[YYYYYYYYYYYYYYYYY] with id com.inodes.datanucleus.model.Key:User("admin") into Redis cache
    at org.datanucleus.api.jdo.NucleusJDOHelper.getJDOExceptionForNucleusException(NucleusJDOHelper.java:680)
    at org.datanucleus.api.jdo.JDOPersistenceManager.getObjectById(JDOPersistenceManager.java:1747)
    at mobi.allshoppings.dao.spi.GenericDAOJDO.get(GenericDAOJDO.java:144)
    at mobi.allshoppings.dao.spi.GenericDAOJDO.get(GenericDAOJDO.java:108)
    at mobi.allshoppings.bdb.tools.BasicDataBuilder.warmUp(BasicDataBuilder.java:49)
    at mobi.allshoppings.bdb.tools.InitAppServlet.init(InitAppServlet.java:21)
    at org.eclipse.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:616)
    at org.eclipse.jetty.servlet.ServletHolder.initialize(ServletHolder.java:396)
    at org.eclipse.jetty.servlet.ServletHandler.initialize(ServletHandler.java:871)
    at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:298)
    at org.eclipse.jetty.webapp.WebAppContext.startWebapp(WebAppContext.java:1349)
    at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1342)
    at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:741)
    at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:505)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:132)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:114)
    at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:61)
    at org.eclipse.jetty.server.handler.ContextHandlerCollection.doStart(ContextHandlerCollection.java:163)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:132)
    at org.eclipse.jetty.server.Server.start(Server.java:387)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:114)
    at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:61)
    at org.eclipse.jetty.server.Server.doStart(Server.java:354)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
    at mobi.allshoppings.jetty.JettyServer.startup(JettyServer.java:62)
    at mobi.allshoppings.cli.StartServer.main(StartServer.java:44)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at mobi.allshoppings.cli.CLI.main(CLI.java:100)
NestedThrowablesStackTrace:
Failed to set object CachedPC : cls=mobi.allshoppings.model.User version=null loadedFlags=[YYYYYYYYYYYYYYYYY] with id com.inodes.datanucleus.model.Key:User("admin") into Redis cache
org.datanucleus.exceptions.NucleusException: Failed to set object CachedPC : cls=mobi.allshoppings.model.User version=null loadedFlags=[YYYYYYYYYYYYYYYYY] with id com.inodes.datanucleus.model.Key:User("admin") into Redis cache
    at org.datanucleus.cache.redis.RedisLevel2Cache.put(RedisLevel2Cache.java:280)
    at org.datanucleus.ExecutionContextImpl.putObjectIntoLevel2CacheInternal(ExecutionContextImpl.java:4914)
    at org.datanucleus.ExecutionContextImpl.putObjectIntoLevel2Cache(ExecutionContextImpl.java:4741)
    at org.datanucleus.ExecutionContextImpl.findObject(ExecutionContextImpl.java:3579)
    at org.datanucleus.ExecutionContextImpl.findObject(ExecutionContextImpl.java:3016)
    at org.datanucleus.api.jdo.JDOPersistenceManager.getObjectById(JDOPersistenceManager.java:1742)
    at mobi.allshoppings.dao.spi.GenericDAOJDO.get(GenericDAOJDO.java:144)
    at mobi.allshoppings.dao.spi.GenericDAOJDO.get(GenericDAOJDO.java:108)
    at mobi.allshoppings.bdb.tools.BasicDataBuilder.warmUp(BasicDataBuilder.java:49)
    at mobi.allshoppings.bdb.tools.InitAppServlet.init(InitAppServlet.java:21)
    at org.eclipse.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:616)
    at org.eclipse.jetty.servlet.ServletHolder.initialize(ServletHolder.java:396)
    at org.eclipse.jetty.servlet.ServletHandler.initialize(ServletHandler.java:871)
    at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:298)
    at org.eclipse.jetty.webapp.WebAppContext.startWebapp(WebAppContext.java:1349)
    at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1342)
    at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:741)
    at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:505)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:132)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:114)
    at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:61)
    at org.eclipse.jetty.server.handler.ContextHandlerCollection.doStart(ContextHandlerCollection.java:163)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:132)
    at org.eclipse.jetty.server.Server.start(Server.java:387)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:114)
    at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:61)
    at org.eclipse.jetty.server.Server.doStart(Server.java:354)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
    at mobi.allshoppings.jetty.JettyServer.startup(JettyServer.java:62)
    at mobi.allshoppings.cli.StartServer.main(StartServer.java:44)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at mobi.allshoppings.cli.CLI.main(CLI.java:100)

正如堆栈所示,在序列化过程中会触发异常。我知道任何将使用 datanucleus 存储的类都必须扩展 Serializable 并且必须使用一些特殊的注释,例如 @PersistenceCapable、@NotPersistant 或 @EmbebedOnly

问题是,当前的生产版本具有完全相同的配置,唯一可能破坏任何 datanucleus 配置的更改是升级本身和两个新类的声明,其中: 已经注释(如在文档和其他工作类中)并且这些类根本不参与启动过程,因此即使它们的配置不好,服务器也应该可以正常启动;但它拒绝。 persitence.xmlpackage-mongodb.orm 看起来还不错(同样,在文档和其他工作类中)。

datanucleus 增强过程和依赖添加到类路径是;据我们所知,正确。

在序列化过程中出现的 Non-Serializable 异常是由于(格式错误?)CachePC 对象(由 datanucleus 构建以包装实际的 User 对象)引起的,该对象的字段是 StateManagerImpl 的一个实例,并且看起来确实如此未实现 Serializable,因此导致异常。


注意:上面的堆栈跟踪与项目的当前配置匹配,它没有直接显示 NoSerializableException,但在调试时我确认这是引发的第一个异常。当 ObjectOutputStream 确定 StateManagerImpl 不是要序列化的有效对象时,它会被引发。当前版本使用XMemcached,如果我们将此版本切换到Memcached,我们可以清楚地看到“Non-Serializable Exception”。 (我们想切换到 Redis,因为最初的服务器被设计为分布式系统;但你会惊讶于它有多少瓶颈)


所以;我们不知道为什么它会尝试序列化 StateManagerImpl;我们认为这是上一个 datanucleus 版本的错误,因此我们切换到 版本 5.1.0-release,但没有成功。应用程序、Jetty 服务器和 servlet 启动正常,我们可以确认 datanucleus 成功解析了 datanucleus.configuration 文件,我们可以获取 PersistanceManager 实例并读取 mongo 数据库。但是当涉及到写入缓存时(这是自动完成的); Redis 或 XMemcached,我们总是得到一个 Non-Serializable 异常,因为 datanucleus 构建了一个带有不可序列化 StateManagerImpl 的 CachedPC。

我们应该从哪里重新开始?有什么问题?我们是否应该将 datanucleus 切换到更受支持的数据访问层?

感谢您的建议。


更新

以下是使用 Memcached 而不是 Redis 时产生的堆栈跟踪(行为相同,再次序列化到 L2 Cache 时会中断)

GRAVE: exception catched
javax.jdo.JDOException: Exception thrown in persistence to xmemcached
    at org.datanucleus.api.jdo.NucleusJDOHelper.getJDOExceptionForNucleusException(NucleusJDOHelper.java:676)
    at org.datanucleus.api.jdo.JDOPersistenceManager.getObjectById(JDOPersistenceManager.java:1747)
    at mobi.allshoppings.dao.spi.GenericDAOJDO.get(GenericDAOJDO.java:144)
    at mobi.allshoppings.dao.spi.GenericDAOJDO.get(GenericDAOJDO.java:108)
    at mobi.allshoppings.bdb.tools.BasicDataBuilder.warmUp(BasicDataBuilder.java:49)
    at mobi.allshoppings.bdb.tools.InitAppServlet.init(InitAppServlet.java:21)
    at org.eclipse.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:616)
    at org.eclipse.jetty.servlet.ServletHolder.initialize(ServletHolder.java:396)
    at org.eclipse.jetty.servlet.ServletHandler.initialize(ServletHandler.java:871)
    at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:298)
    at org.eclipse.jetty.webapp.WebAppContext.startWebapp(WebAppContext.java:1349)
    at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1342)
    at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:741)
    at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:505)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:132)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:114)
    at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:61)
    at org.eclipse.jetty.server.handler.ContextHandlerCollection.doStart(ContextHandlerCollection.java:163)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:132)
    at org.eclipse.jetty.server.Server.start(Server.java:387)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:114)
    at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:61)
    at org.eclipse.jetty.server.Server.doStart(Server.java:354)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
    at mobi.allshoppings.jetty.JettyServer.startup(JettyServer.java:62)
    at mobi.allshoppings.cli.StartServer.main(StartServer.java:44)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at mobi.allshoppings.cli.CLI.main(CLI.java:100)
NestedThrowablesStackTrace:
java.lang.IllegalArgumentException: Non-serializable object
    at net.rubyeye.xmemcached.transcoders.BaseSerializingTranscoder.serialize(BaseSerializingTranscoder.java:99)
    at net.rubyeye.xmemcached.transcoders.SerializingTranscoder.encode(SerializingTranscoder.java:211)
    at net.rubyeye.xmemcached.command.text.TextStoreCommand.encodeValue(TextStoreCommand.java:199)
    at net.rubyeye.xmemcached.command.text.TextStoreCommand.encode(TextStoreCommand.java:155)
    at net.rubyeye.xmemcached.impl.MemcachedTCPSession.wrapMessage(MemcachedTCPSession.java:189)
    at com.google.code.yanf4j.core.impl.AbstractSession.write(AbstractSession.java:383)
    at net.rubyeye.xmemcached.impl.MemcachedConnector.send(MemcachedConnector.java:556)
    at net.rubyeye.xmemcached.XMemcachedClient.sendCommand(XMemcachedClient.java:322)
    at net.rubyeye.xmemcached.XMemcachedClient.sendStoreCommand(XMemcachedClient.java:2537)
    at net.rubyeye.xmemcached.XMemcachedClient.set(XMemcachedClient.java:1369)
    at net.rubyeye.xmemcached.XMemcachedClient.set(XMemcachedClient.java:1428)
    at net.rubyeye.xmemcached.XMemcachedClient.set(XMemcachedClient.java:1415)
    at org.datanucleus.cache.xmemcached.XmemcachedLevel2Cache.put(XmemcachedLevel2Cache.java:177)
    at org.datanucleus.ExecutionContextImpl.putObjectIntoLevel2CacheInternal(ExecutionContextImpl.java:4914)
    at org.datanucleus.ExecutionContextImpl.putObjectIntoLevel2Cache(ExecutionContextImpl.java:4741)
    at org.datanucleus.ExecutionContextImpl.findObject(ExecutionContextImpl.java:3579)
    at org.datanucleus.ExecutionContextImpl.findObject(ExecutionContextImpl.java:3016)
    at org.datanucleus.api.jdo.JDOPersistenceManager.getObjectById(JDOPersistenceManager.java:1742)
    at mobi.allshoppings.dao.spi.GenericDAOJDO.get(GenericDAOJDO.java:144)
    at mobi.allshoppings.dao.spi.GenericDAOJDO.get(GenericDAOJDO.java:108)
    at mobi.allshoppings.bdb.tools.BasicDataBuilder.warmUp(BasicDataBuilder.java:49)
    at mobi.allshoppings.bdb.tools.InitAppServlet.init(InitAppServlet.java:21)
    at org.eclipse.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:616)
    at org.eclipse.jetty.servlet.ServletHolder.initialize(ServletHolder.java:396)
    at org.eclipse.jetty.servlet.ServletHandler.initialize(ServletHandler.java:871)
    at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:298)
    at org.eclipse.jetty.webapp.WebAppContext.startWebapp(WebAppContext.java:1349)
    at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1342)
    at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:741)
    at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:505)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:132)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:114)
    at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:61)
    at org.eclipse.jetty.server.handler.ContextHandlerCollection.doStart(ContextHandlerCollection.java:163)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:132)
    at org.eclipse.jetty.server.Server.start(Server.java:387)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:114)
    at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:61)
    at org.eclipse.jetty.server.Server.doStart(Server.java:354)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
    at mobi.allshoppings.jetty.JettyServer.startup(JettyServer.java:62)
    at mobi.allshoppings.cli.StartServer.main(StartServer.java:44)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at mobi.allshoppings.cli.CLI.main(CLI.java:100)
Caused by: java.io.NotSerializableException: org.datanucleus.state.StateManagerImpl
    - field (class "org.datanucleus.identity.IdentityReference", name: "client", type: "class java.lang.Object")
    - object (class "org.datanucleus.identity.IdentityReference", org.datanucleus.identity.IdentityReference@44fd7ba4)
    - field (class "org.datanucleus.cache.CachedPC", name: "id", type: "class java.lang.Object")
    - object (class "org.datanucleus.cache.CachedPC", CachedPC : cls=mobi.allshoppings.model.Address version=null loadedFlags=[YYYYYYYYY])
    - custom writeObject data (class "java.util.HashMap")
    - object (class "java.util.HashMap", {0=1, 1=CachedPC : cls=mobi.allshoppings.model.Address version=null loadedFlags=[YYYYYYYYY], 2=null, 3=null, 4=CachedPC : cls=mobi.allshoppings.model.ContactInfo version=null loadedFlags=[YYYYYYYYYYYY], 5=Sun Oct 29 04:57:34 CST 2017, 6=null, 7=true, 8=User("admin"), 9=null, 10=Sun Oct 29 05:03:40 CST 2017, 11=0, 12=true, 13=CachedPC : cls=mobi.allshoppings.model.UserSecurity version=null loadedFlags=[YYYYYYYYYYYYYYYYY], 14=null, 15=00000000880E0D76, 16=CachedPC : cls=mobi.allshoppings.model.tools.ViewLocation version=null loadedFlags=[Y]})
    - field (class "org.datanucleus.cache.CachedPC", name: "fieldValues", type: "interface java.util.Map")
    - root object (class "org.datanucleus.cache.CachedPC", CachedPC : cls=mobi.allshoppings.model.User version=null loadedFlags=[YYYYYYYYYYYYYYYYY])
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1182)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
    at java.util.HashMap.internalWriteEntries(HashMap.java:1790)
    at java.util.HashMap.writeObject(HashMap.java:1363)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:1128)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
    at net.rubyeye.xmemcached.transcoders.BaseSerializingTranscoder.serialize(BaseSerializingTranscoder.java:94)
    ... 48 more

此外,以下是在序列化过程中实际抛出异常之前ObjectOutputStream 的 debugInfoStack 的状态:

这是异常创建之前的状态:

- object (class "java.lang.StackTraceElement", java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1182))
- element of array (index: 0)
- array (class "[Ljava.lang.StackTraceElement;", size: 74)
- field (class "java.lang.Throwable", name: "stackTrace", type: "class [Ljava.lang.StackTraceElement;")
- custom writeObject data (class "java.lang.Throwable")
- root object (class "java.io.NotSerializableException", java.io.NotSerializableException: org.datanucleus.state.StateManagerImpl
- field (class "org.datanucleus.identity.IdentityReference", name: "client", type: "class java.lang.Object")
- object (class "org.datanucleus.identity.IdentityReference", org.datanucleus.identity.IdentityReference@44fd7ba4)
- field (class "org.datanucleus.cache.CachedPC", name: "id", type: "class java.lang.Object")
- object (class "org.datanucleus.cache.CachedPC", CachedPC : cls=mobi.allshoppings.model.Address version=null loadedFlags=[YYYYYYYYY])
- custom writeObject data (class "java.util.HashMap")
- object (class "java.util.HashMap", {0=1, 1=CachedPC : cls=mobi.allshoppings.model.Address version=null loadedFlags=[YYYYYYYYY], 2=null, 3=null, 4=CachedPC : cls=mobi.allshoppings.model.ContactInfo version=null loadedFlags=[YYYYYYYYYYYY], 5=Sun Oct 29 04:57:34 CST 2017, 6=null, 7=true, 8=User("admin"), 9=null, 10=Sun Oct 29 05:03:40 CST 2017, 11=0, 12=true, 13=CachedPC : cls=mobi.allshoppings.model.UserSecurity version=null loadedFlags=[YYYYYYYYYYYYYYYYY], 14=null, 15=00000000880E0D76, 16=CachedPC : cls=mobi.allshoppings.model.tools.ViewLocation version=null loadedFlags=[Y]})
- field (class "org.datanucleus.cache.CachedPC", name: "fieldValues", type: "interface java.util.Map")
- root object (class "org.datanucleus.cache.CachedPC", CachedPC : cls=mobi.allshoppings.model.User version=null loadedFlags=[YYYYYYYYYYYYYYYYY]))

这个状态显示了一个我之前没有注意到的抑制异常(以及触发异常之前的最后一个状态):

- object (class "java.util.ArrayList", [])
- field (class "java.util.Collections$UnmodifiableCollection", name: "c", type: "interface java.util.Collection")
- object (class "java.util.Collections$UnmodifiableList", [])
- field (class "java.lang.Throwable", name: "suppressedExceptions", type: "interface java.util.List")
- custom writeObject data (class "java.lang.Throwable")
- root object (class "java.io.NotSerializableException", java.io.NotSerializableException: org.datanucleus.state.StateManagerImpl
- field (class "org.datanucleus.identity.IdentityReference", name: "client", type: "class java.lang.Object")
- object (class "org.datanucleus.identity.IdentityReference", org.datanucleus.identity.IdentityReference@44fd7ba4)
- field (class "org.datanucleus.cache.CachedPC", name: "id", type: "class java.lang.Object")
- object (class "org.datanucleus.cache.CachedPC", CachedPC : cls=mobi.allshoppings.model.Address version=null loadedFlags=[YYYYYYYYY])
- custom writeObject data (class "java.util.HashMap")
- object (class "java.util.HashMap", {0=1, 1=CachedPC : cls=mobi.allshoppings.model.Address version=null loadedFlags=[YYYYYYYYY], 2=null, 3=null, 4=CachedPC : cls=mobi.allshoppings.model.ContactInfo version=null loadedFlags=[YYYYYYYYYYYY], 5=Sun Oct 29 04:57:34 CST 2017, 6=null, 7=true, 8=User("admin"), 9=null, 10=Sun Oct 29 05:03:40 CST 2017, 11=0, 12=true, 13=CachedPC : cls=mobi.allshoppings.model.UserSecurity version=null loadedFlags=[YYYYYYYYYYYYYYYYY], 14=null, 15=00000000880E0D76, 16=CachedPC : cls=mobi.allshoppings.model.tools.ViewLocation version=null loadedFlags=[Y]})
- field (class "org.datanucleus.cache.CachedPC", name: "fieldValues", type: "interface java.util.Map")
- root object (class "org.datanucleus.cache.CachedPC", CachedPC : cls=mobi.allshoppings.model.User version=null loadedFlags=[YYYYYYYYYYYYYYYYY]))

唯一拥有Lists作为属性的类,是User类的一个属性,它有如下声明:

@PersistenceCapable(detachable="true")
@EmbeddedOnly
public class UserSecurity implements Serializable {

而且我没有看到它在缓存过程中被调用,仅在 mongodb 读取期间被调用。再说一遍:mongodb 的讲座效果很好,但作为 datanucleus 尝试缓存刚刚读取的对象;它失败。所以,我不知道那个不可修改的列表是从哪里来的。

【问题讨论】:

  • 为什么不发布你的课程,这个 CachedPC 对象中有什么?因为 CachedPC 对象没有这样的字段,根据 github.com/datanucleus/datanucleus-core/blob/master/src/main/… 。这个 StateManager 对象在哪个字段中? Jedis 是在进行连载。
  • “更多支持”是什么意思?我发现持久性提供程序得到了很好的支持,并且比我尝试过的所有其他提供程序的响应速度更快。他们的文档说要使用 groups.io 或 gitter。
  • @DN1 实际上,这与 CachedPC 类在某些时候拥有一个 StateManagerImpl 对象完全相同。我不太确定序列化过程是如何完成的;但是 Jedis 或 Memcached 都会产生同样的错误;因此,据我所知,datanucleus 将 StateManagerImpl 注入到 CachedPC,然后再将其传递给 L2 缓存驱动程序。我将发布堆栈以我的 memcached 控制器为荣。
  • @BillyFrost 更多支持我的意思是一个数据访问层,在搜索此类问题的解决方案时,您可以找到一个可以帮助解决问题的实际社区,而不仅仅是一页结果回答如“我们希望 Google App Engine 尽快更新其配置”。我知道 datanucleus 和 JDO 支持许多数据存储,实际上是一项很好的技术;但这不是我第一次发现使用它们难以追踪的问题
  • 你的类定义了这个字段在哪里,它是什么类型,以及为什么它可能在那里。我没有看到你的课。然后定义了放入 CachedPC 中的内容,以及从我在此类中完成的代码中看到的内容github.com/datanucleus/datanucleus-core/blob/master/src/main/… 因此,当您确定 CachedPC 的哪个字段是这个 StateManagerImpl 时,您可以从哪个字段返回它是存储对照,发现问题

标签: java jdo datanucleus jedis


【解决方案1】:

所以,也许我有点太咸了;但事实证明,实际上我们的问题是由 Datanucleus 错误引起的:https://github.com/datanucleus/datanucleus-core/issues/283

文档说嵌入对象不应该有 ID,因为它们直接喜欢具有 ID 的容器对象(在“同表”方案下)http://www.datanucleus.org/products/datanucleus/jdo/mapping.html#embedded_pc 但是我们的嵌入对象被赋予了一个不应该存在的 IdentityReference。

我注意到StateManagerImpl是序列化嵌入对象时异常的原因,但我没有过多关注导致StateManagerImpl序列化的IdentityReference对象;导致缓存 L2 写入错误。这就是这个错误的全部意义所在。

因此,解决方案是克隆 datanucleus-core 项目,在本地构建和安装最新版本,然后重新构建我们的项目,将 datanucleus-core 依赖项更改为本地文件。它工作得很好。

在深入研究了 datanucleus 及其代码本身的文档之后,我更加确信 datanucleus 实际上是一个非常好的数据存储抽象,我们会将它保留在我们的项目中(但我仍然相信支持和错误消息含糊不清)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-14
    • 2017-03-01
    • 2011-06-10
    相关资源
    最近更新 更多