1 /* 2 * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.marlin; 27 28 import static com.sun.marlin.MarlinConst.LOG_UNSAFE_MALLOC; 29 import java.lang.reflect.Field; 30 import java.security.AccessController; 31 import java.security.PrivilegedAction; 32 import sun.misc.Unsafe; 33 34 /** 35 * 36 */ 37 final class OffHeapArray { 38 39 // unsafe reference 40 static final Unsafe UNSAFE; 41 // size of int / float 42 static final int SIZE_INT; 43 44 static { 45 UNSAFE = AccessController.doPrivileged(new PrivilegedAction<Unsafe>() { 46 @Override 47 public Unsafe run() { 48 Unsafe ref = null; 49 try { 50 final Field field = Unsafe.class.getDeclaredField("theUnsafe"); 51 field.setAccessible(true); 52 ref = (Unsafe) field.get(null); 53 } catch (Exception e) { 54 throw new InternalError("Unable to get sun.misc.Unsafe instance", e); 55 } 56 return ref; 57 } 58 }); 59 60 SIZE_INT = Unsafe.ARRAY_INT_INDEX_SCALE; 61 } 62 63 /* members */ 64 long address; 65 long length; 66 int used; 67 68 OffHeapArray(final Object parent, final long len) { 69 // note: may throw OOME: 70 this.address = UNSAFE.allocateMemory(len); 71 this.length = len; 72 this.used = 0; 73 if (LOG_UNSAFE_MALLOC) { 74 MarlinUtils.logInfo(System.currentTimeMillis() 75 + ": OffHeapArray.allocateMemory = " 76 + len + " to addr = " + this.address); 77 } 78 79 // Register a cleaning function to ensure freeing off-heap memory: 80 MarlinUtils.getCleaner().register(parent, () -> this.free()); 81 } 82 83 /* 84 * As realloc may change the address, updating address is MANDATORY 85 * @param len new array length 86 * @throws OutOfMemoryError if the allocation is refused by the system 87 */ 88 void resize(final long len) { 89 // note: may throw OOME: 90 this.address = UNSAFE.reallocateMemory(address, len); 91 this.length = len; 92 if (LOG_UNSAFE_MALLOC) { 93 MarlinUtils.logInfo(System.currentTimeMillis() 94 + ": OffHeapArray.reallocateMemory = " 95 + len + " to addr = " + this.address); 96 } 97 } 98 99 void free() { 100 UNSAFE.freeMemory(this.address); 101 if (LOG_UNSAFE_MALLOC) { 102 MarlinUtils.logInfo(System.currentTimeMillis() 103 + ": OffHeapArray.freeMemory = " 104 + this.length 105 + " at addr = " + this.address); 106 } 107 this.address = 0L; 108 } 109 110 void fill(final byte val) { 111 UNSAFE.setMemory(this.address, this.length, val); 112 } 113 }