- 37. Do not shadow or obscure identifiers in subscopes
- 38. Do not declare more than one variable per declaration
- 39. Use meaningful symbolic constants to represent literal values in program logic
- 40. Properly encode relationships in constant definitions
- 41. Return an empty array or collection instead of a null value for methods that return an array or collection
- 42. Use exceptions only for exceptional conditions
- 43. Use a try-with-resources statement to safely handle closeable resources
- 44. Do not use assertions to verify the absence of runtime errors
- 45. Use the same type for the second and third operands in conditional expressions
- 46. Do not serialize direct handles to system resources
- 47. Prefer using iterators over enumerations
- 48. Do not use direct buffers for short-lived, infrequently used objects
- 49. Remove short-lived objects from long-lived container objects
48. Do not use direct buffers for short-lived, infrequently used objects
The new I/O (NIO) classes in java.nio allow the creation and use of direct buffers. These buffers tremendously increase throughput for repeated I/O activities. However, their creation and reclamation is more expensive than the creation and reclamation of heap-based non-direct buffers because direct buffers are managed using OS-specific native code. This added management cost makes direct buffers a poor choice for single-use or infrequently used cases. Direct buffers are also outside the scope of Java’s garbage collector; consequently, injudicious use of direct buffers can cause memory leaks. Finally, frequent allocation of large direct buffers can cause an OutOfMemoryError.
Noncompliant Code Example
This noncompliant code example uses both a short-lived local object, rarelyUsed-Buffer, and a long-lived, heavily used object, heavilyUsedBuffer. Both are allocated in non-heap memory; neither is garbage collected.
ByteBuffer rarelyUsedBuffer = ByteBuffer.allocateDirect(8192); // Use rarelyUsedBuffer once ByteBuffer heavilyUsedBuffer = ByteBuffer.allocateDirect(8192); // Use heavilyUsedBuffer many times
This compliant solution uses an indirect buffer to allocate the short-lived, infrequently used object. The heavily used buffer appropriately continues to use a non-heap, non-garbage-collected direct buffer.
ByteBuffer rarelyUsedBuffer = ByteBuffer.allocate(8192); // Use rarelyUsedBuffer once ByteBuffer heavilyUsedBuffer = ByteBuffer.allocateDirect(8192); // Use heavilyUsedBuffer many times
Direct buffers are beyond the scope of Java’s garbage collector and can cause memory leaks if they are used injudiciously. In general, direct buffers should be allocated only when their use provides a significant gain in performance.