为什么 jar 文件会出现 TDB2 "Lock already held" 问题?
Why TDB2 "Lock already held" problem occurring from jar file?
我正在开发 apache Jena 应用程序。当我 运行 来自 Intellij IDE 的代码时它工作正常但是如果我生成一个 jar 文件并且 运行 终端中的 jar 文件它不起作用。
我得到的错误:
Uncaught exeption ! : org.apache.jena.dboe.base.file.AlreadyLocked: Failed to get a lock: file='/home/iam/OneDrive/Internship/current_data/myTDB/tdb.lock': Lock already held
我正在使用:
- Apache 耶拿 (3.15.0)。 (TDB2)
- Gradle6.5
- JVM:11.0.8 (Ubuntu 11.0.8+10-post-Ubuntu-0ubuntu120.04)
TDB 特定的锁定问题
我会参考 TDB FAQs 作为第一个参考:
This exception is a result of TDBs automatic multi-JVM usage prevention, as noted in the earlier Can I share a TDB dataset between multiple applications? question a TDB database can only be safely used by a single JVM otherwise data corruption may occur. From 1.1.0 onwards TDB automatically enforces this restriction wherever possible and you will get this exception if you attempt to access a database which is being accessed from another JVM.
基本上您不能同时从两个进程打开同一个 TDB 数据库位置。
至于您的具体情况似乎发生了什么:
- 您 运行 IntelliJ 内部的一些代码可以访问 TDB 数据库。这将创建锁定文件,假设 IntelliJ 没有分叉新的 JVM,那么锁定文件将与 IntelliJ 进程本身相关联。
或者,如果 IntelliJ 正在分叉新进程,那么 you/it 不会
完成后明确停止 运行ning 进程。
- 然后您尝试 运行 您构建的 JAR 文件。这会尝试打开 TDB 数据库,发现存在锁定文件并指向活动的 IntelliJ 进程,因此拒绝访问数据库。
您很可能需要先退出并重新启动 IntelliJ,因为该进程(或子进程)将成为锁持有者。然后,您需要确保从 IntelliJ 内部 运行 生成的任何代码都是作为一个新进程生成的,并且在您想要单独测试构建的 JAR 时停止该进程。
另一种可能的方法是使您的 TDB 数据库位置可配置,这样您在 IntelliJ 中测试时与 运行在 JAR 文件中测试时使用不同的位置。这样您就可以避免两个进程竞争数据库锁的任何可能性,因为它们会使用不同的数据库。
文件系统特定的锁定问题
我还注意到您的数据库似乎位于 OneDrive 位置 - /home/iam/OneDrive/Internship/current_data/myTDB/tdb.lock
- 也可能是此处发生了文件系统问题。
- 由于 OneDrive 不一定将所有文件都存储在本地,因此用于将其装载到系统上的文件系统实际上可能不支持锁定该位置。尽管您的代码在 IntelliJ 中完全 运行 的事实似乎表明情况并非如此。但是,您可以尝试使用绝对位于本地驱动器上的数据库位置来排除这种情况。
- 该位置被其他一些进程隐式锁定(可能是 OneDrive 本身,可能是 IntelliJ,或者完全是其他东西)
对于 2,在您的情况下这似乎更可能是问题,您可以尝试找出持有锁的原因,例如How to list processes locking file 找出其他进程正在锁定它并进一步调查。
我正在开发 apache Jena 应用程序。当我 运行 来自 Intellij IDE 的代码时它工作正常但是如果我生成一个 jar 文件并且 运行 终端中的 jar 文件它不起作用。
我得到的错误:
Uncaught exeption ! : org.apache.jena.dboe.base.file.AlreadyLocked: Failed to get a lock: file='/home/iam/OneDrive/Internship/current_data/myTDB/tdb.lock': Lock already held
我正在使用:
- Apache 耶拿 (3.15.0)。 (TDB2)
- Gradle6.5
- JVM:11.0.8 (Ubuntu 11.0.8+10-post-Ubuntu-0ubuntu120.04)
TDB 特定的锁定问题
我会参考 TDB FAQs 作为第一个参考:
This exception is a result of TDBs automatic multi-JVM usage prevention, as noted in the earlier Can I share a TDB dataset between multiple applications? question a TDB database can only be safely used by a single JVM otherwise data corruption may occur. From 1.1.0 onwards TDB automatically enforces this restriction wherever possible and you will get this exception if you attempt to access a database which is being accessed from another JVM.
基本上您不能同时从两个进程打开同一个 TDB 数据库位置。
至于您的具体情况似乎发生了什么:
- 您 运行 IntelliJ 内部的一些代码可以访问 TDB 数据库。这将创建锁定文件,假设 IntelliJ 没有分叉新的 JVM,那么锁定文件将与 IntelliJ 进程本身相关联。
或者,如果 IntelliJ 正在分叉新进程,那么 you/it 不会 完成后明确停止 运行ning 进程。 - 然后您尝试 运行 您构建的 JAR 文件。这会尝试打开 TDB 数据库,发现存在锁定文件并指向活动的 IntelliJ 进程,因此拒绝访问数据库。
您很可能需要先退出并重新启动 IntelliJ,因为该进程(或子进程)将成为锁持有者。然后,您需要确保从 IntelliJ 内部 运行 生成的任何代码都是作为一个新进程生成的,并且在您想要单独测试构建的 JAR 时停止该进程。
另一种可能的方法是使您的 TDB 数据库位置可配置,这样您在 IntelliJ 中测试时与 运行在 JAR 文件中测试时使用不同的位置。这样您就可以避免两个进程竞争数据库锁的任何可能性,因为它们会使用不同的数据库。
文件系统特定的锁定问题
我还注意到您的数据库似乎位于 OneDrive 位置 - /home/iam/OneDrive/Internship/current_data/myTDB/tdb.lock
- 也可能是此处发生了文件系统问题。
- 由于 OneDrive 不一定将所有文件都存储在本地,因此用于将其装载到系统上的文件系统实际上可能不支持锁定该位置。尽管您的代码在 IntelliJ 中完全 运行 的事实似乎表明情况并非如此。但是,您可以尝试使用绝对位于本地驱动器上的数据库位置来排除这种情况。
- 该位置被其他一些进程隐式锁定(可能是 OneDrive 本身,可能是 IntelliJ,或者完全是其他东西)
对于 2,在您的情况下这似乎更可能是问题,您可以尝试找出持有锁的原因,例如How to list processes locking file 找出其他进程正在锁定它并进一步调查。