@@ -154,21 +154,16 @@ public Random current() {
154
154
155
155
if (maxDirectMemory == 0 || !hasUnsafe () || !PlatformDependent0 .hasDirectBufferNoCleanerConstructor ()) {
156
156
USE_DIRECT_BUFFER_NO_CLEANER = false ;
157
- DIRECT_MEMORY_COUNTER = null ;
158
157
} else {
159
158
USE_DIRECT_BUFFER_NO_CLEANER = true ;
160
159
if (maxDirectMemory < 0 ) {
161
160
maxDirectMemory = maxDirectMemory0 ();
162
- if (maxDirectMemory <= 0 ) {
163
- DIRECT_MEMORY_COUNTER = null ;
164
- } else {
165
- DIRECT_MEMORY_COUNTER = new AtomicLong ();
166
- }
167
- } else {
168
- DIRECT_MEMORY_COUNTER = new AtomicLong ();
169
161
}
170
162
}
163
+
164
+ DIRECT_MEMORY_COUNTER = new AtomicLong ();
171
165
DIRECT_MEMORY_LIMIT = maxDirectMemory ;
166
+
172
167
logger .debug ("-Dio.netty.maxDirectMemory: {} bytes" , maxDirectMemory );
173
168
174
169
int tryAllocateUninitializedArray =
@@ -380,14 +375,6 @@ public static <K, V> ConcurrentMap<K, V> newConcurrentHashMap(Map<? extends K, ?
380
375
return new ConcurrentHashMap <K , V >(map );
381
376
}
382
377
383
- /**
384
- * Try to deallocate the specified direct {@link ByteBuffer}. Please note this method does nothing if
385
- * the current platform does not support this operation or the specified buffer is not a direct buffer.
386
- */
387
- public static void freeDirectBuffer (ByteBuffer buffer ) {
388
- CLEANER .freeDirectBuffer (buffer );
389
- }
390
-
391
378
public static long directBufferAddress (ByteBuffer buffer ) {
392
379
return PlatformDependent0 .directBufferAddress (buffer );
393
380
}
@@ -584,6 +571,45 @@ public static void setMemory(long address, long bytes, byte value) {
584
571
PlatformDependent0 .setMemory (address , bytes , value );
585
572
}
586
573
574
+ public static ByteBuffer allocateDirect (int capacity ) {
575
+ return USE_DIRECT_BUFFER_NO_CLEANER
576
+ ? PlatformDependent .allocateDirectNoCleaner (capacity )
577
+ : allocateDirectJVM (capacity );
578
+ }
579
+
580
+ public static void freeDirectBuffer (ByteBuffer buffer ) {
581
+ if (USE_DIRECT_BUFFER_NO_CLEANER ) {
582
+ PlatformDependent .freeDirectNoCleaner (buffer );
583
+ } else {
584
+ PlatformDependent .freeDirectBufferJVM (buffer );
585
+ }
586
+ }
587
+
588
+ /**
589
+ * Allocate a new {@link ByteBuffer} with the given {@code capacity}. {@link ByteBuffer}s allocated with
590
+ * this method <strong>MUST</strong> be deallocated via {@link #freeDirectNoCleaner(ByteBuffer)}.
591
+ */
592
+ public static ByteBuffer allocateDirectJVM (int capacity ) {
593
+ incrementMemoryCounter (capacity );
594
+ try {
595
+ return ByteBuffer .allocateDirect (capacity );
596
+ } catch (Throwable e ) {
597
+ decrementMemoryCounter (capacity );
598
+ throwException (e );
599
+ return null ;
600
+ }
601
+ }
602
+
603
+ /**
604
+ * Try to deallocate the specified direct {@link ByteBuffer}. Please note this method does nothing if
605
+ * the current platform does not support this operation or the specified buffer is not a direct buffer.
606
+ */
607
+ public static void freeDirectBufferJVM (ByteBuffer buffer ) {
608
+ int capacity = buffer .capacity ();
609
+ CLEANER .freeDirectBuffer (buffer );
610
+ decrementMemoryCounter (capacity );
611
+ }
612
+
587
613
/**
588
614
* Allocate a new {@link ByteBuffer} with the given {@code capacity}. {@link ByteBuffer}s allocated with
589
615
* this method <strong>MUST</strong> be deallocated via {@link #freeDirectNoCleaner(ByteBuffer)}.
@@ -632,32 +658,32 @@ public static void freeDirectNoCleaner(ByteBuffer buffer) {
632
658
}
633
659
634
660
private static void incrementMemoryCounter (int capacity ) {
635
- if (DIRECT_MEMORY_COUNTER != null ) {
636
- for (;;) {
637
- long usedMemory = DIRECT_MEMORY_COUNTER .get ();
638
- long newUsedMemory = usedMemory + capacity ;
639
- if (newUsedMemory > DIRECT_MEMORY_LIMIT ) {
640
- throw new OutOfDirectMemoryError ("failed to allocate " + capacity
641
- + " byte(s) of direct memory (used: " + usedMemory + ", max: " + DIRECT_MEMORY_LIMIT + ')' );
642
- }
643
- if (DIRECT_MEMORY_COUNTER .compareAndSet (usedMemory , newUsedMemory )) {
644
- break ;
645
- }
661
+ for (;;) {
662
+ long usedMemory = DIRECT_MEMORY_COUNTER .get ();
663
+ long newUsedMemory = usedMemory + capacity ;
664
+ if (DIRECT_MEMORY_LIMIT > 0 && newUsedMemory > DIRECT_MEMORY_LIMIT ) {
665
+ throw new OutOfDirectMemoryError ("failed to allocate " + capacity
666
+ + " byte(s) of direct memory (used: " + usedMemory + ", max: " + DIRECT_MEMORY_LIMIT + ')' );
667
+ }
668
+ if (DIRECT_MEMORY_COUNTER .compareAndSet (usedMemory , newUsedMemory )) {
669
+ break ;
646
670
}
647
671
}
648
672
}
649
673
650
674
private static void decrementMemoryCounter (int capacity ) {
651
- if (DIRECT_MEMORY_COUNTER != null ) {
652
- long usedMemory = DIRECT_MEMORY_COUNTER .addAndGet (-capacity );
653
- assert usedMemory >= 0 ;
654
- }
675
+ long usedMemory = DIRECT_MEMORY_COUNTER .addAndGet (-capacity );
676
+ assert usedMemory >= 0 : "Used memory is negative: " + usedMemory ;
655
677
}
656
678
657
679
public static boolean useDirectBufferNoCleaner () {
658
680
return USE_DIRECT_BUFFER_NO_CLEANER ;
659
681
}
660
682
683
+ public static long usedDirectMemory () {
684
+ return DIRECT_MEMORY_COUNTER .get ();
685
+ }
686
+
661
687
/**
662
688
* Compare two {@code byte} arrays for equality. For performance reasons no bounds checking on the
663
689
* parameters is performed.
0 commit comments