Posts java off heap
Post
Cancel

java off heap

Off heap memory allocation

  • sun.misc.Unsafe: JVM internal API로서 생성자 호출없이 Object를 생성한다거나 하는 다양한 기능의 API가 있으나
    • 대표적으로 Non-JVM 영역(off-heap, direct memory)에 메모리를 할당하여 사용할 수 있음
      • JVM 영역 밖의 메모리를 사용 ==> GC Overhead가 없음. 대신 leak이 나지 않게 개발자가 메모리 관리를 잘 해야 함
        • 당연히, Off-heap 메모리 사용량은 JVM Memory 모니터링에 잡히지 않으며, 프로세스 메모리 사용량을 모니터링 해야함
      • Large and Long lived object를 메모리에 올릴 때 이점이 있음
    • Off-heap 메모리를 사용할 수 있는 방법이 Unsafe만 있는 것은 아님
      • java nio의 ByteBuffer 역시 jvm heap외 영역에 메모리 할당. GC의 영향을 받지 않음
      • DirectByteBuffer
      • -XX:MaxDirectMemorySize=N

Sample Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
public class TestUnsafe {
    Unsafe unsafe;

    public static Unsafe getUnsafe() {
        try {
            Field f = Unsafe.class.getDeclaredField("theUnsafe");
            f.setAccessible(true);
            return (Unsafe) f.get(null);
        } catch(Exception e) {
            throw new RuntimeException("Can not obtain unsafe object.");
        }
    }
    
    @Before
    public void setUp() {
        unsafe = getUnsafe();
    }
    
    class DirectIntArray {
    
        private final static long INT_SIZE_IN_BYTES = 4;
    
        private final long startIndex;
    
        public DirectIntArray(long size) {
            startIndex = unsafe.allocateMemory(size * INT_SIZE_IN_BYTES);
            unsafe.setMemory(startIndex, size * INT_SIZE_IN_BYTES, (byte) 0);
        }
    
        public void setValue(long index, int value) {
            unsafe.putInt(index(index), value);
        }
    
        public int getValue(long index) {
            return unsafe.getInt(index(index));
        }
    
        private long index(long offset) {
            return startIndex + offset * INT_SIZE_IN_BYTES;
        }
    
        public void destroy() {
            unsafe.freeMemory(startIndex);
        }
    }
    
    @Test
    public void testDirectIntArray() throws Exception {
        long maximum = Integer.MAX_VALUE + 1L;
    
        DirectIntArray directIntArray = new DirectIntArray(maximum);
        directIntArray.setValue(0L, 10);
        directIntArray.setValue(maximum, 20);
        assertEquals(10, directIntArray.getValue(0L));
        assertEquals(20, directIntArray.getValue(maximum));
    
        directIntArray.destroy();
    }

참고

This post is licensed under CC BY 4.0 by the author.