【问题标题】:java.util.Prefs throwing BackingStoreException - Why?java.util.Prefs 抛出 BackingStoreException - 为什么?
【发布时间】:2011-01-02 21:49:54
【问题描述】:

我有一个缓存启动时 SOAP 调用的微小/简单结果的系统

我需要实例能够在启动时重新加载其缓存(以防 SOAP 服务失效),并且还需要处理多个实例使用此缓存文件的可能性

我选择使用java.util.prefs,但 Java 的内置自动同步线程间歇性失败(1% 的时间使用默认 JVM 30 秒后备存储同步)转储以下异常:

Jan 8, 2010 12:30:07 PM java.util.prefs.FileSystemPreferences syncWorld
WARNING: Couldn't flush user prefs: java.util.prefs.BackingStoreException: Couldn't get file lock.

我怀疑 this bug 但这已在 1.5(tiger-b40) 中修复,我们在此框中的 java 5 是“1.5.0_16-b02”。

我现在怀疑这可能是因为我们有多个 JVM 共享这个后备存储,尽管这似乎不会在我们的其他机器上发生。

谁能证实这一点? 有什么风险(如果有的话)?

如果我的方法有缺陷,我应该使用什么作为替代方法?

【问题讨论】:

  • 给出一些代码,别指望我们猜到
  • 听起来肯定与让多个 JVM 尝试使用同一个文件有关。人们倾向于使用数据库来集中数据以供多个进程同时共享和修改。
  • java.util.prefs API 是一只火鸡。我建议忽略它并使用其他人实际使用的东西,例如数据库。
  • 我实际上根本不想共享数据,我只是想创建一个廉价的配置(来自 SOAP 调用)缓存。 DB 太重了
  • 对于那些投票赞成 Bozho 的人:没有代码,这是失败的 Java SYSTEM 线程之一!大声笑

标签: java preferences


【解决方案1】:

“我现在怀疑这可能是因为我们有多个 JVM 共享这个后备存储”

绝对有可能! 如果两个 JVM 尝试同时锁定文件,那么您将看到这种情况。

具体细节取决于锁的类型、操作系统和文件系统。

您可能想尝试将导致此问题的操作包装在 try/catch 块中,然后在失败时重试该操作。

【讨论】:

【解决方案2】:

不使用首选项,只需使用任何可序列化的 Map 并创建一个非常简单的缓存类,将其序列化和反序列化为随机生成的临时文件名(第一次初始化时生成的文件名)。由于它只是一个缓存,因此您可以捕获任何异常并在发生异常时将缓存重置为其初始状态,因此它将从原始数据源(在您的情况下为 SOAP 服务)重新获取。因此,如果您不想担心 serialVersionUID 或任何兼容性问题,则无需担心。

【讨论】:

  • 问题是我需要实例能够在启动时重新加载它们的缓存(以防 SOAP 服务失效)并且还处理多个实例使用此缓存文件的可能性。我将添加到 OP
【解决方案3】:

我在码头遇到了同样的问题。我发现以下解决了这个问题。

.systemPrefs 添加到您的 JRE 目录,并为正在运行抱怨的进程的用户提供访问权限。

完成后,进入 Jetty 目录并打开 start.ini 文件

-Djava.util.prefs.userRoot={user's home directory}

-Djava.util.prefs.systemRoot={user's home directory}

添加完这些行后,我重新启动了 jetty,发现错误消失了。

【讨论】:

  • 我想这可以通过更改该特定 JRE 使用的存储来实现,以避免与您必须运行的其他 JRE 发生冲突。感谢分享
猜你喜欢
  • 1970-01-01
  • 2016-04-04
  • 2021-12-20
  • 2020-02-01
  • 2021-03-05
  • 2021-03-19
  • 2014-01-24
  • 1970-01-01
  • 2023-03-14
相关资源
最近更新 更多