1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty5.buffer.api;
17
18 import io.netty5.buffer.api.internal.ArcDrop;
19 import io.netty5.buffer.api.internal.CleanerDrop;
20 import io.netty5.buffer.api.internal.MemoryManagerOverride;
21
22 import java.nio.ByteBuffer;
23 import java.util.function.Function;
24 import java.util.function.Supplier;
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 public final class SensitiveBufferAllocator implements BufferAllocator {
44 private static final BufferAllocator INSTANCE = new SensitiveBufferAllocator(null);
45 private final AllocatorControl control = () -> this;
46 private final Function<Drop<Buffer>, Drop<Buffer>> decorator = this::decorate;
47 private final MemoryManager manager;
48
49
50
51
52
53
54 public static BufferAllocator sensitiveOffHeapAllocator() {
55 MemoryManager memoryManagerOverride = MemoryManagerOverride.configuredOrDefaultManager(null);
56 if (memoryManagerOverride != null) {
57 return new SensitiveBufferAllocator(memoryManagerOverride);
58 }
59 return INSTANCE;
60 }
61
62 private SensitiveBufferAllocator(MemoryManager manager) {
63 this.manager = manager;
64 }
65
66 @Override
67 public boolean isPooling() {
68 return false;
69 }
70
71 @Override
72 public AllocationType getAllocationType() {
73 return StandardAllocationTypes.OFF_HEAP;
74 }
75
76 @Override
77 public Buffer allocate(int size) {
78 MemoryManager manager = getManager();
79 return manager.allocateShared(control, size, decorator, getAllocationType());
80 }
81
82 private Drop<Buffer> decorate(Drop<Buffer> base) {
83 MemoryManager manager = getManager();
84 return CleanerDrop.wrap(ArcDrop.wrap(new ZeroingDrop(manager, control, base)), manager);
85 }
86
87 private MemoryManager getManager() {
88 if (manager != null) {
89 return MemoryManagerOverride.configuredOrDefaultManager(manager);
90 }
91 return MemoryManager.instance();
92 }
93
94 @Override
95 public Supplier<Buffer> constBufferSupplier(byte[] bytes) {
96 Buffer origin = copyOf(bytes).makeReadOnly();
97 return () -> origin.copy(true);
98 }
99
100 @Override
101 public void close() {
102 }
103
104 private static final class ZeroingDrop implements Drop<Buffer> {
105 private final MemoryManager manager;
106 private final Drop<Buffer> base;
107 private final AllocatorControl control;
108
109 ZeroingDrop(MemoryManager manager, AllocatorControl control, Drop<Buffer> base) {
110 this.manager = manager;
111 this.control = control;
112 this.base = base;
113 }
114
115 @Override
116 public void drop(Buffer obj) {
117
118
119 Object memory = manager.unwrapRecoverableMemory(obj);
120 manager.clearMemory(memory);
121 base.drop(obj);
122 }
123
124 @Override
125 public Drop<Buffer> fork() {
126
127
128 throw new UnsupportedOperationException();
129 }
130
131 @Override
132 public void attach(Buffer obj) {
133 base.attach(obj);
134 }
135
136 @Override
137 public String toString() {
138 return "ZeroingDrop(" + base + ')';
139 }
140 }
141 }