Berkeley DB Java Edition 2.1.30 Change Log

Changes since Release 2.0.90

For additional details, please see the documentation and Release Notes included in your download package or on our website.

Log File On-Disk Format Changes:

New Features:

  1. Multi-key secondary databases are now supported, providing direct support for many-to-many and one-to-many relationships. See
    • examples/je/
    [#13842] (2.1.30)

General Environment Changes:

  1. Improved performance for in-cache read access when there is no record lock contention among threads. [#10609] (2.1.30)

  2. Increased concurrency during a join operation by removing an unnecessary lock. [#11833] (2.1.30)

  3. Fixed a bug where the cursor configuration was not honored by Cursor.count. A read lock was always acquired, even when the cursor was configured for dirty read. [#11833] (2.1.30)

  4. Improved the log cleaner:
    • Various performance improvements were made.
    • Multiple cleaner threads are now supported. For some applications, configuring more than one cleaner thread is necessary in order for the cleaner to maintain total log utilization below the configured threshold (50% by default). The je.cleaner.threads property is used to configure the number of threads. The default is one thread.
    • A look ahead cache is implemented to reduce Btree lookups during cleaning. The memory allocated to this cache is configured using the je.cleaner.lookAheadCacheSize property. The default value is 8 KB.
    • All cleaner configuration properties are now mutable (can be changed at any time).
    [#12831] (2.1.30)

  5. The collections API now ensures that a transaction is aborted by TransactionRunner when an Error (e.g., OutOfMemoryError) occurs, since the application may continue and the thread must be disassociated from the transaction. [#13145] (2.1.30)

  6. JE will detect a Java 1.5 runtime, and will use 1.5 synchronization classes for a significant performance increase. [#13327] (2.1.30)

  7. Environment.truncateDatabase() and removeDatabase() are significantly faster. [#13333] (2.1.30)

  8. JE was triggering log cleaning purely based on the total log utilization. This could result in situations where log files with low utilization were not examined for cleaning because the threshold limit was met. Now log files less than 5% utilized are cleaned, irrespective of the total log utilization. This reclaims unused disk space and allows the log cleaner to "get ahead". Note that as always, the threshold can be changed by setting the je.cleaner.minFileUtilization property. [#13335] (2.1.30)

  9. JE will detect a Java 1.5 runtime, and will use the 1.5 Adler32 class for checksums for a significant performance increase. JE previously used its own implementation to work around a Sun JVM bug fixed in 1.5. [#13354] (2.1.30)

  10. Fixed a bug which caused a NullPointerException when getDatabaseNames is called and the first database (name order wise) has been renamed or removed. [#13377] (2.1.30)

  11. Fixed a bug where an internal hang could occur between the checkpointer thread and a thread that calls Environment.truncateDatabase or Environment.removeDatabase. [#13381] (2.1.30)

  12. The behavior of Cursor.getSearchBothRange() did not properly match the documentation. In the past a range search was done on the key as well as the data value when finding a record to return. This has been fixed so that an exact match is required for the key, and a range search is done for the data. [#13388] (2.1.30)

  13. JE now detects data records with 0 length data and uses a special case optimization to reduce their in-memory overhead. [#13438] (2.1.30)

  14. Fixed a bug where could be thrown at environment instantiation for applications which use records with duplicate keys, and periodically delete the entire duplicate set (of records with the same key). [#13501] (2.1.30)

  15. Made a performance fix to the locking implementation which benefits the case where there is high contention for a single record. In this situation, a CPU profile of the application would show a lot of time spent in [#13605] (2.1.30)

  16. Added integrity checks to ensure that log file corruption (resulting from a system problem, for example) is detected as early as possible. [#13611] (2.1.30)

  17. A rare edge case requiring the repeated insertion and deletion of sets of duplicate records and a specific abort and commit sequence could cause Cursor.count() to return the wrong count for a set of duplicate records. The count would be off by 1. [#13726] (2.1.30)

  18. Improved memory budgeting during log cleaning in small-cache situations. [#13818] (2.1.30)

  19. JE cache memory utilization was underestimated for 64 bit JVMs. JE now determines at runtime whether the JVM is 32b or 64b JVM, as well as whether it is Java 1.5 or 1.4 and adjusts memory usage calculations accordingly. The 32b/64b determination is based on the system property. An application may override the 32bit/64 bit determination by setting the system property je.forceJVMArch to either "32" or "64". The JVM version determination uses the same logic employed by [#13227] for choosing to use Java 1.5 synchronization, and can be overridden using the property je.disable.java5.latches. [#13865] (2.1.30)

  20. Improved performance by reducing the number of internal calls to [#13879] (2.1.30);

  21. The performance of internal cursors were improved by providing a custom hashCode() implementation. [#13896] (2.1.30)

  22. Fixed a bug where IOExceptions could cause subsequent checksum exceptions. [#13898] (2.1.30)

  23. Replaced an intentional use of a ClassCastException during record locking with instanceof. This could be confusing for users who had set a breakpoint on ClassCastException and was also slower than using instanceof. [#13913] (2.1.30)

  24. Fixed an unreported bug that could cause a NullPointerException when calling Cursor.count. [#13940]

  25. Fixed an unreported bug that could cause duplicate key records to be skipped by a cursor in a rare corner case. [#13940]

  26. Throw DeadlockException directly, not an internal subclass of it, when a lock timeout or transaction timeout occurs. This makes it easier to identify a deadlock as such when viewing a stack trace. [#13954] (2.1.30)

API Changes:

  1. The DbDump utility has a new -d switch to indicate an output directory for the dumped data. [#13145] (2.1.30)

  2. Added the je.txn.deadlockStackTrace property to allow getting a stack trace in deadlock exception messages without having to modify JE sources. Added the je.txn.dumpLocks property to dump the entire lock table in a deadlock exception message, for debugging. The output of the entire lock table can be large, but is useful for determining the locking relationships between records. [#13377] (2.1.30)

  3. Several new JE properties were added as a result of the changes to use Java 5 locking primitives for the JE latch class when available. je.env.fairLatches is now a static property (i.e. it is the same across all environments and the value is that of the last environment opened. A new property, je.disable.java5.latches will force loading old style latches if set. One use case might be an application that wants to configure latches with interruptibility. Java 5 latches are by default not interruptible, and the JE proprietary implementation is both interruptible and faster than Java 5 locking with interruptibility set, so in such a use case the most optimal choice is to use je.disable.java5.latches property to force traditional JE latches to be loaded.(2.1.30)

  4. A new property, je.lock.nLockTables was added to specify the number of lock tables. While the default is 1, increasing this number can improve multithreaded concurrency. The value of this property should be a prime number, and should ideally be the nearest prime that is not greater than the number of concurrent threads. [#13587] (2.1.30)

  5. JE supports a new no-locking mode, for improved performance. When using this mode, the application must ensure that there is no concurrent activity on the database. Concurrent activity while in no-locking mode can lead to database corruption. In addition, log cleaning is disabled in no-locking mode, so the application is responsible for managing log cleaning through explicit calls to the Environment.cleanLog() method.

    No-locking mode is controlled by EnvironmentConfig.setLocking(boolean). The default is true (locking is enabled). Locking cannot be disabled in a transactional environment. [#13788] (2.1.30)

  6. Database.preload() is significantly faster, returns statistics on preload activity, and can be configured to preload data records as well as internal database nodes. The signature has been changed to Preload Stats preload(PreloadConfig), and older forms of preload() are deprecated.

    preload() now returns a PreloadStats object which contains status (success, time_exceeded, or cache_exceeded) and stats (# LNs, BINs, INs, etc. loaded). It now takes PreloadConfig as argument to specify maxBytes, maxMillisecs, and whether to load LN's or not. (2.1.30)

Utility Changes:

  1. JE utility programs such as DbDump may now be run with java -jar je.jar DbDump <args> instead of specifying the full class name. [#13469] (2.1.30)

  2. DbCacheSize is an aid for estimating cache sizes. See the header comments for <jeHome>/src/com/sleepycat/je/util/ for an explanation of how to use this utility. (2.1.30)

Configuration, Documentation, and Build Changes:

  1. JE still supports both Java 1.4 and 1.5 at runtime, but now requires Java 1.5 for compiling the source.

  2. A new documentation guide, "Writing Transactional Applications with Berkeley DB, Java Edition" is now available in both the distribution and OTN Berkeley DB Java Edition page.

  3. JE FAQs have been updated and expanded and are now available through the OTN Berkeley DB Java Edition page.