0%

SourceAnalysis-Unsafe

阅读更多

1 前言

Unsafe这个类是用于执行低级别、不安全操作的方法集合。尽管这个类和所有的方法都是公开的(public),但是这个类的使用仍然受限,你无法在自己的java程序中直接使用该类,因为只有授信的代码才能获得该类的实例

Java最初被设计为一种安全的受控环境。尽管如此,HotSpot还是包含了一个后门sun.misc.Unsafe,提供了一些可以直接操控内存和线程的底层操作。Unsafe被JDK广泛应用于java.nio和并发包等实现中,这个不安全的类提供了一个观察HotSpot JVM内部结构并且可以对其进行修改,但是不建议在生产环境中使用

在JDK标准库的实现中许多地方会出现Unsafe的身影,因此了解一下Unsafe还是有必要的

2 put/get

以int类型为例进行说明,其他基本类型以及Object类似

3 getInt

该方法从给定的对象中取出指定偏移量(offset)的int类型的字段

当满足下列条件之一时,结果才是正确的,否则结果是未定义的

  1. offset是通过objectFieldOffset方法获取,并且o的类型与该字段所属的类型兼容
  2. offseto是通过staticFieldOffset方法与staticFieldBase方法获取
  3. o的类型是数组,且offset = B + N * S,其中B通过arrayBaseOffset方法获取,即数组的起始偏移量;S通过arrayIndexScale方法获取,即数组单个元素的偏移量;N代表第N个元素
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
/**
* Fetches a value from a given Java variable.
* More specifically, fetches a field or array element within the given
* object <code>o</code> at the given offset, or (if <code>o</code> is
* null) from the memory address whose numerical value is the given
* offset.
* <p>
* The results are undefined unless one of the following cases is true:
* <ul>
* <li>The offset was obtained from {@link #objectFieldOffset} on
* the {@link Field} of some Java field and the object
* referred to by <code>o</code> is of a class compatible with that
* field's class.
* <p>
* <li>The offset and object reference <code>o</code> (either null or
* non-null) were both obtained via {@link #staticFieldOffset}
* and {@link #staticFieldBase} (respectively) from the
* reflective {@link Field} representation of some Java field.
* <p>
* <li>The object referred to by <code>o</code> is an array, and the offset
* is an integer of the form <code>B+N*S</code>, where <code>N</code> is
* a valid index into the array, and <code>B</code> and <code>S</code> are
* the values obtained by {@link #arrayBaseOffset} and {@link
* #arrayIndexScale} (respectively) from the array's class. The value
* referred to is the <code>N</code><em>th</em> element of the array.
* <p>
* </ul>
* <p>
* If one of the above cases is true, the call references a specific Java
* variable (field or array element). However, the results are undefined
* if that variable is not in fact of the type returned by this method.
* <p>
* This method refers to a variable by means of two parameters, and so
* it provides (in effect) a <em>double-register</em> addressing mode
* for Java variables. When the object reference is null, this method
* uses its offset as an absolute address. This is similar in operation
* to methods such as {@link #getInt(long)}, which provide (in effect) a
* <em>single-register</em> addressing mode for non-Java variables.
* However, because Java variables may have a different layout in memory
* from non-Java variables, programmers should not assume that these
* two addressing modes are ever equivalent. Also, programmers should
* remember that offsets from the double-register addressing mode cannot
* be portably confused with longs used in the single-register addressing
* mode.
*
* @param o Java heap object in which the variable resides, if any, else
* null
* @param offset indication of where the variable resides in a Java heap
* object, if any, else a memory address locating the variable
* statically
* @return the value fetched from the indicated Java variable
* @throws RuntimeException No defined exceptions are thrown, not even
* {@link NullPointerException}
*/
public native int getInt(Object o, long offset);

3.1 putInt

putInt将值x存入对象o的指定偏移量offset

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* Stores a value into a given Java variable.
* <p>
* The first two parameters are interpreted exactly as with
* {@link #getInt(Object, long)} to refer to a specific
* Java variable (field or array element). The given value
* is stored into that variable.
* <p>
* The variable must be of the same type as the method
* parameter <code>x</code>.
*
* @param o Java heap object in which the variable resides, if any, else
* null
* @param offset indication of where the variable resides in a Java heap
* object, if any, else a memory address locating the variable
* statically
* @param x the value to store into the indicated Java variable
* @throws RuntimeException No defined exceptions are thrown, not even
* {@link NullPointerException}
*/
public native void putInt(Object o, long offset, int x);

3.2 else

这里仅列出其他所有基本类型的put/get方法,具体说明请参考putInt和getInt方法

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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
/**
* Fetches a reference value from a given Java variable.
*
* @see #getInt(Object, long)
*/
public native Object getObject(Object o, long offset);

/**
* Stores a reference value into a given Java variable.
* <p>
* Unless the reference <code>x</code> being stored is either null
* or matches the field type, the results are undefined.
* If the reference <code>o</code> is non-null, car marks or
* other store barriers for that object (if the VM requires them)
* are updated.
*
* @see #putInt(Object, int, int)
*/
public native void putObject(Object o, long offset, Object x);

/**
* @see #getInt(Object, long)
*/
public native boolean getBoolean(Object o, long offset);

/**
* @see #putInt(Object, int, int)
*/
public native void putBoolean(Object o, long offset, boolean x);

/**
* @see #getInt(Object, long)
*/
public native byte getByte(Object o, long offset);

/**
* @see #putInt(Object, int, int)
*/
public native void putByte(Object o, long offset, byte x);

/**
* @see #getInt(Object, long)
*/
public native short getShort(Object o, long offset);

/**
* @see #putInt(Object, int, int)
*/
public native void putShort(Object o, long offset, short x);

/**
* @see #getInt(Object, long)
*/
public native char getChar(Object o, long offset);

/**
* @see #putInt(Object, int, int)
*/
public native void putChar(Object o, long offset, char x);

/**
* @see #getInt(Object, long)
*/
public native long getLong(Object o, long offset);

/**
* @see #putInt(Object, int, int)
*/
public native void putLong(Object o, long offset, long x);

/**
* @see #getInt(Object, long)
*/
public native float getFloat(Object o, long offset);

/**
* @see #putInt(Object, int, int)
*/
public native void putFloat(Object o, long offset, float x);

/**
* @see #getInt(Object, long)
*/
public native double getDouble(Object o, long offset);

/**
* @see #putInt(Object, int, int)
*/
public native void putDouble(Object o, long offset, double x);

/**
* This method, like all others with 32-bit offsets, was native
* in a previous release but is now a wrapper which simply casts
* the offset to a long value. It provides backward compatibility
* with bytecodes compiled against 1.4.
*
* @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
* See {@link #staticFieldOffset}.
*/
@Deprecated
public int getInt(Object o, int offset) {
return getInt(o, (long) offset);
}

/**
* @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
* See {@link #staticFieldOffset}.
*/
@Deprecated
public void putInt(Object o, int offset, int x) {
putInt(o, (long) offset, x);
}

/**
* @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
* See {@link #staticFieldOffset}.
*/
@Deprecated
public Object getObject(Object o, int offset) {
return getObject(o, (long) offset);
}

/**
* @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
* See {@link #staticFieldOffset}.
*/
@Deprecated
public void putObject(Object o, int offset, Object x) {
putObject(o, (long) offset, x);
}

/**
* @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
* See {@link #staticFieldOffset}.
*/
@Deprecated
public boolean getBoolean(Object o, int offset) {
return getBoolean(o, (long) offset);
}

/**
* @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
* See {@link #staticFieldOffset}.
*/
@Deprecated
public void putBoolean(Object o, int offset, boolean x) {
putBoolean(o, (long) offset, x);
}

/**
* @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
* See {@link #staticFieldOffset}.
*/
@Deprecated
public byte getByte(Object o, int offset) {
return getByte(o, (long) offset);
}

/**
* @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
* See {@link #staticFieldOffset}.
*/
@Deprecated
public void putByte(Object o, int offset, byte x) {
putByte(o, (long) offset, x);
}

/**
* @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
* See {@link #staticFieldOffset}.
*/
@Deprecated
public short getShort(Object o, int offset) {
return getShort(o, (long) offset);
}

/**
* @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
* See {@link #staticFieldOffset}.
*/
@Deprecated
public void putShort(Object o, int offset, short x) {
putShort(o, (long) offset, x);
}

/**
* @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
* See {@link #staticFieldOffset}.
*/
@Deprecated
public char getChar(Object o, int offset) {
return getChar(o, (long) offset);
}

/**
* @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
* See {@link #staticFieldOffset}.
*/
@Deprecated
public void putChar(Object o, int offset, char x) {
putChar(o, (long) offset, x);
}

/**
* @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
* See {@link #staticFieldOffset}.
*/
@Deprecated
public long getLong(Object o, int offset) {
return getLong(o, (long) offset);
}

/**
* @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
* See {@link #staticFieldOffset}.
*/
@Deprecated
public void putLong(Object o, int offset, long x) {
putLong(o, (long) offset, x);
}

/**
* @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
* See {@link #staticFieldOffset}.
*/
@Deprecated
public float getFloat(Object o, int offset) {
return getFloat(o, (long) offset);
}

/**
* @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
* See {@link #staticFieldOffset}.
*/
@Deprecated
public void putFloat(Object o, int offset, float x) {
putFloat(o, (long) offset, x);
}

/**
* @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
* See {@link #staticFieldOffset}.
*/
@Deprecated
public double getDouble(Object o, int offset) {
return getDouble(o, (long) offset);
}

/**
* @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
* See {@link #staticFieldOffset}.
*/
@Deprecated
public void putDouble(Object o, int offset, double x) {
putDouble(o, (long) offset, x);
}

//These work on values in the C heap.

/**
* Fetches a value from a given memory address. If the address is zero, or
* does not point into a block obtained from {@link #allocateMemory}, the
* results are undefined.
*
* @see #allocateMemory
*/
public native byte getByte(long address);

/**
* Stores a value into a given memory address. If the address is zero, or
* does not point into a block obtained from {@link #allocateMemory}, the
* results are undefined.
*
* @see #getByte(long)
*/
public native void putByte(long address, byte x);

/**
* @see #getByte(long)
*/
public native short getShort(long address);

/**
* @see #putByte(long, byte)
*/
public native void putShort(long address, short x);

/**
* @see #getByte(long)
*/
public native char getChar(long address);

/**
* @see #putByte(long, byte)
*/
public native void putChar(long address, char x);

/**
* @see #getByte(long)
*/
public native int getInt(long address);

/**
* @see #putByte(long, byte)
*/
public native void putInt(long address, int x);

/**
* @see #getByte(long)
*/
public native long getLong(long address);

/**
* @see #putByte(long, byte)
*/
public native void putLong(long address, long x);

/**
* @see #getByte(long)
*/
public native float getFloat(long address);

/**
* @see #putByte(long, byte)
*/
public native void putFloat(long address, float x);

/**
* @see #getByte(long)
*/
public native double getDouble(long address);

/**
* @see #putByte(long, byte)
*/
public native void putDouble(long address, double x);

4 putVolatile/getVolatile

这类方法从指定对象中以volatile的方式读取或者写入相应类型的值。等效于给相应的字段加上volatile关键字,即实现volatile读写的内存语义(插入相应的内存屏障)

那为什么不直接使用volatile关键字来修饰呢?因为只想在某些特定的地方拥有volatile读写的内存语义,这样可以提高效率,如果粗暴地直接加上volatile关键字,那么可能会导致性能的下降。这种优化手段一般我们不需要考虑,这是JDK标准库实现才会使用的手法,毕竟Unsafe是不推荐正常Java代码使用的

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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
/**
* Fetches a reference value from a given Java variable, with volatile
* load semantics. Otherwise identical to {@link #getObject(Object, long)}
*/
public native Object getObjectVolatile(Object o, long offset);

/**
* Stores a reference value into a given Java variable, with
* volatile store semantics. Otherwise identical to {@link #putObject(Object, long, Object)}
*/
public native void putObjectVolatile(Object o, long offset, Object x);

/**
* Volatile version of {@link #getInt(Object, long)}
*/
public native int getIntVolatile(Object o, long offset);

/**
* Volatile version of {@link #putInt(Object, long, int)}
*/
public native void putIntVolatile(Object o, long offset, int x);

/**
* Volatile version of {@link #getBoolean(Object, long)}
*/
public native boolean getBooleanVolatile(Object o, long offset);

/**
* Volatile version of {@link #putBoolean(Object, long, boolean)}
*/
public native void putBooleanVolatile(Object o, long offset, boolean x);

/**
* Volatile version of {@link #getByte(Object, long)}
*/
public native byte getByteVolatile(Object o, long offset);

/**
* Volatile version of {@link #putByte(Object, long, byte)}
*/
public native void putByteVolatile(Object o, long offset, byte x);

/**
* Volatile version of {@link #getShort(Object, long)}
*/
public native short getShortVolatile(Object o, long offset);

/**
* Volatile version of {@link #putShort(Object, long, short)}
*/
public native void putShortVolatile(Object o, long offset, short x);

/**
* Volatile version of {@link #getChar(Object, long)}
*/
public native char getCharVolatile(Object o, long offset);

/**
* Volatile version of {@link #putChar(Object, long, char)}
*/
public native void putCharVolatile(Object o, long offset, char x);

/**
* Volatile version of {@link #getLong(Object, long)}
*/
public native long getLongVolatile(Object o, long offset);

/**
* Volatile version of {@link #putLong(Object, long, long)}
*/
public native void putLongVolatile(Object o, long offset, long x);

/**
* Volatile version of {@link #getFloat(Object, long)}
*/
public native float getFloatVolatile(Object o, long offset);

/**
* Volatile version of {@link #putFloat(Object, long, float)}
*/
public native void putFloatVolatile(Object o, long offset, float x);

/**
* Volatile version of {@link #getDouble(Object, long)}
*/
public native double getDoubleVolatile(Object o, long offset);

/**
* Volatile version of {@link #putDouble(Object, long, double)}
*/
public native void putDoubleVolatile(Object o, long offset, double x);

5 putOrder/getOrder

这类方法从指定对象中读取或者写入相应类型的值

  1. putOrder等效于插入StoreStore屏障
  2. getOrder等效于插入LoadLoad屏障
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* Version of {@link #putObjectVolatile(Object, long, Object)}
* that does not guarantee immediate visibility of the store to
* other threads. This method is generally only useful if the
* underlying field is a Java volatile (or if an array cell, one
* that is otherwise only accessed using volatile accesses).
*/
public native void putOrderedObject(Object o, long offset, Object x);

/**
* Ordered/Lazy version of {@link #putIntVolatile(Object, long, int)}
*/
public native void putOrderedInt(Object o, long offset, int x);

/**
* Ordered/Lazy version of {@link #putLongVolatile(Object, long, long)}
*/
public native void putOrderedLong(Object o, long offset, long x);

6 park/unpark

unpark()方法可以唤醒一个线程,如果线程处于非阻塞状态则获取一枚许可,但是多次调用unpark()方法也仅能获取一枚许可

park()方法用于消耗一枚许可,当没有可用许可时便阻塞指定线程。即如果在调用park()方法之前调用过unpark()方法,那么本次park()将不会阻塞该线程

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
/**
* Unblock the given thread blocked on <tt>park</tt>, or, if it is
* not blocked, cause the subsequent call to <tt>park</tt> not to
* block. Note: this operation is "unsafe" solely because the
* caller must somehow ensure that the thread has not been
* destroyed. Nothing special is usually required to ensure this
* when called from Java (in which there will ordinarily be a live
* reference to the thread) but this is not nearly-automatically
* so when calling from native code.
*
* @param thread the thread to unpark.
*/
public native void unpark(Object thread);

/**
* Block current thread, returning when a balancing
* <tt>unpark</tt> occurs, or a balancing <tt>unpark</tt> has
* already occurred, or the thread is interrupted, or, if not
* absolute and time is not zero, the given time nanoseconds have
* elapsed, or if absolute, the given deadline in milliseconds
* since Epoch has passed, or spuriously (i.e., returning for no
* "reason"). Note: This operation is in the Unsafe class only
* because <tt>unpark</tt> is, so it would be strange to place it
* elsewhere.
*/
public native void park(boolean isAbsolute, long time);

7 CAS

CAS即compare and swap,比较当前值与期望值,如果相等,那么替换为指定值,如果不相等,什么也不做。该操作是原子操作

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
/**
* Atomically update Java variable to <tt>x</tt> if it is currently
* holding <tt>expected</tt>.
*
* @return <tt>true</tt> if successful
*/
public final native boolean compareAndSwapObject(Object o, long offset,
Object expected,
Object x);

/**
* Atomically update Java variable to <tt>x</tt> if it is currently
* holding <tt>expected</tt>.
*
* @return <tt>true</tt> if successful
*/
public final native boolean compareAndSwapInt(Object o, long offset,
int expected,
int x);

/**
* Atomically update Java variable to <tt>x</tt> if it is currently
* holding <tt>expected</tt>.
*
* @return <tt>true</tt> if successful
*/
public final native boolean compareAndSwapLong(Object o, long offset,
long expected,
long x);

8 offset

这类方法用于获取内存偏移量,这些偏移量在Java代码中是没用的,因为Java完全屏蔽了内存结构,这些偏移量只用于配合Unsafe的put、get方法

8.1 staticFieldOffset

返回指定静态字段在其所属类型的内存结构中的偏移量。任意一个字段的offset与base都是相同的,任意两个不同的字段都不可能有相同的偏移量(废话)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* Report the location of a given field in the storage allocation of its
* class. Do not expect to perform any sort of arithmetic on this offset;
* it is just a cookie which is passed to the unsafe heap memory accessors.
* <p>
* <p>Any given field will always have the same offset and base, and no
* two distinct fields of the same class will ever have the same offset
* and base.
* <p>
* <p>As of 1.4.1, offsets for fields are represented as long values,
* although the Sun JVM does not use the most significant 32 bits.
* However, JVM implementations which store static fields at absolute
* addresses can use long offsets and null base pointers to express
* the field locations in a form usable by {@link #getInt(Object, long)}.
* Therefore, code which will be ported to such JVMs on 64-bit platforms
* must preserve all bits of static field offsets.
*
* @see #getInt(Object, long)
*/
public native long staticFieldOffset(Field f);

8.2 objectFieldOffset

返回指定实例字段在其所属类型的内存结构中的偏移量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* Report the location of a given static field, in conjunction with {@link
* #staticFieldBase}.
* <p>Do not expect to perform any sort of arithmetic on this offset;
* it is just a cookie which is passed to the unsafe heap memory accessors.
* <p>
* <p>Any given field will always have the same offset, and no two distinct
* fields of the same class will ever have the same offset.
* <p>
* <p>As of 1.4.1, offsets for fields are represented as long values,
* although the Sun JVM does not use the most significant 32 bits.
* It is hard to imagine a JVM technology which needs more than
* a few bits to encode an offset within a non-array object,
* However, for consistency with other methods in this class,
* this method reports its result as a long value.
*
* @see #getInt(Object, long)
*/
public native long objectFieldOffset(Field f);

8.3 staticFieldBase

1
2
3
4
5
6
7
8
9
10
11
12
/**
* Report the location of a given static field, in conjunction with {@link
* #staticFieldOffset}.
* <p>Fetch the base "Object", if any, with which static fields of the
* given class can be accessed via methods like {@link #getInt(Object,
* long)}. This value may be null. This value may refer to an object
* which is a "cookie", not guaranteed to be a real Object, and it should
* not be used in any way except as argument to the get and put routines in
* this class.
*/
public native Object staticFieldBase(Field f);

8.4 arrayBaseOffset

返回数组类型中第一个元素的偏移量,因为Java中数组的内存结构中并不仅有元素的内存空间,还有一些额外的信息需要存储,比如Mark word,元数据指针,数组长度等等。因此数组中第一个元素的相对偏移量(相对于数组起始地址)并不是0

1
2
3
4
5
6
7
8
9
10
11
/**
* Report the offset of the first element in the storage allocation of a
* given array class. If {@link #arrayIndexScale} returns a non-zero value
* for the same class, you may use that scale factor, together with this
* base offset, to form new offsets to access elements of arrays of the
* given class.
*
* @see #getInt(Object, long)
* @see #putInt(Object, long, int)
*/
public native int arrayBaseOffset(Class arrayClass);

8.5 arrayIndexScale

返回数组中每个元素所占的偏移量?

1
2
3
4
5
6
7
8
9
10
11
12
/**
* Report the scale factor for addressing elements in the storage
* allocation of a given array class. However, arrays of "narrow" types
* will generally not work properly with accessors like {@link
* #getByte(Object, int)}, so the scale factor for such classes is reported
* as zero.
*
* @see #arrayBaseOffset
* @see #getInt(Object, long)
* @see #putInt(Object, long, int)
*/
public native int arrayIndexScale(Class arrayClass);

9 获取Unsafe实例

Unsafe类是如此地不安全,以至于JDK开发者增加了很多特殊限制来访问它

  1. 私有的构造器
  2. 工厂方法getUnsafe()的调用器只能被Bootloader加载,否则抛出SecurityException 异常

不过,我们可以通过反射机制轻松获取Unsafe的一个实例

1
2
3
4
5
6
7
8
9
public static Unsafe getUnsafe(){
try{
Field f=Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
return (Unsafe)f.get(null);
}catch(Exception e){
return null;
}
}

10 参考