1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.util;
19
20 import java.lang.reflect.Field;
21 import java.nio.ByteBuffer;
22 import java.security.AccessController;
23 import java.security.PrivilegedAction;
24
25 import org.apache.commons.logging.Log;
26 import org.apache.commons.logging.LogFactory;
27 import org.apache.hadoop.hbase.classification.InterfaceAudience;
28 import org.apache.hadoop.hbase.classification.InterfaceStability;
29
30 import sun.misc.Unsafe;
31 import sun.nio.ch.DirectBuffer;
32
33 @InterfaceAudience.Private
34 @InterfaceStability.Evolving
35 @edu.umd.cs.findbugs.annotations.SuppressWarnings(value="REC_CATCH_EXCEPTION",
36 justification="If exception, presume unaligned")
37 public final class UnsafeAccess {
38
39 private static final Log LOG = LogFactory.getLog(UnsafeAccess.class);
40
41 public static final Unsafe theUnsafe;
42
43
44 public static final int BYTE_ARRAY_BASE_OFFSET;
45
46
47
48
49 static final long UNSAFE_COPY_THRESHOLD = 1024L * 1024L;
50 static {
51 theUnsafe = (Unsafe) AccessController.doPrivileged(new PrivilegedAction<Object>() {
52 @Override
53 public Object run() {
54 try {
55 Field f = Unsafe.class.getDeclaredField("theUnsafe");
56 f.setAccessible(true);
57 return f.get(null);
58 } catch (Throwable e) {
59 LOG.warn("sun.misc.Unsafe is not accessible", e);
60 }
61 return null;
62 }
63 });
64
65 if(theUnsafe != null){
66 BYTE_ARRAY_BASE_OFFSET = theUnsafe.arrayBaseOffset(byte[].class);
67 } else{
68 BYTE_ARRAY_BASE_OFFSET = -1;
69 }
70 }
71
72 private UnsafeAccess(){}
73
74
75
76
77
78
79
80
81
82
83 public static void copy(byte[] src, int srcOffset, ByteBuffer dest, int destOffset, int length) {
84 long destAddress = destOffset;
85 Object destBase = null;
86 if (dest.isDirect()) {
87 destAddress = destAddress + ((DirectBuffer) dest).address();
88 } else {
89 destAddress = destAddress + BYTE_ARRAY_BASE_OFFSET + dest.arrayOffset();
90 destBase = dest.array();
91 }
92 long srcAddress = srcOffset + BYTE_ARRAY_BASE_OFFSET;
93 unsafeCopy(src, srcAddress, destBase, destAddress, length);
94 }
95
96 private static void unsafeCopy(Object src, long srcAddr, Object dst, long destAddr, long len) {
97 while (len > 0) {
98 long size = (len > UNSAFE_COPY_THRESHOLD) ? UNSAFE_COPY_THRESHOLD : len;
99 theUnsafe.copyMemory(src, srcAddr, dst, destAddr, len);
100 len -= size;
101 srcAddr += size;
102 destAddr += size;
103 }
104 }
105
106
107
108
109
110
111
112
113
114
115
116 public static void copy(ByteBuffer src, int srcOffset, byte[] dest, int destOffset,
117 int length) {
118 long srcAddress = srcOffset;
119 Object srcBase = null;
120 if (src.isDirect()) {
121 srcAddress = srcAddress + ((DirectBuffer) src).address();
122 } else {
123 srcAddress = srcAddress + BYTE_ARRAY_BASE_OFFSET + src.arrayOffset();
124 srcBase = src.array();
125 }
126 long destAddress = destOffset + BYTE_ARRAY_BASE_OFFSET;
127 unsafeCopy(srcBase, srcAddress, dest, destAddress, length);
128 }
129
130
131
132
133
134
135
136
137
138
139
140 public static void copy(ByteBuffer src, int srcOffset, ByteBuffer dest, int destOffset,
141 int length) {
142 long srcAddress, destAddress;
143 Object srcBase = null, destBase = null;
144 if (src.isDirect()) {
145 srcAddress = srcOffset + ((DirectBuffer) src).address();
146 } else {
147 srcAddress = srcOffset + src.arrayOffset() + BYTE_ARRAY_BASE_OFFSET;
148 srcBase = src.array();
149 }
150 if (dest.isDirect()) {
151 destAddress = destOffset + ((DirectBuffer) dest).address();
152 } else {
153 destAddress = destOffset + BYTE_ARRAY_BASE_OFFSET + dest.arrayOffset();
154 destBase = dest.array();
155 }
156 unsafeCopy(srcBase, srcAddress, destBase, destAddress, length);
157 }
158 }