先来说说Unsafe吧,它的全类名是sun.misc.Unsafe,这是一个java不推荐的编程使用的类,只在源码中使用,它的构造方法被私有化了,不能去new,但是有一个getUnsafe方法:
@CallerSensitive
public static Unsafe getUnsafe() {
Class var0 = Reflection.getCallerClass();
if (var0.getClassLoader() != null) {
throw new SecurityException("Unsafe");
} else {
return theUnsafe;
}
}
该方法表示,拿到当前类的类加载器,如果该类加载器是BootClassLoader,那么就会返回null ,才会返回unsafe对象,我们创建的类一般是AppClassLoader,而不是BootClassLoader,所以使用这个方法会抛出异常,那怎么使用这个类呢?,下面是一个小案例
public class JDK7ConcurrtHashMap {
public static void main(String[] args) {
Unsafe unsafe = Person.getUnsafe();
int si = unsafe.arrayIndexScale(String[].class);
int offset = unsafe.arrayBaseOffset(String[].class);
System.out.println(unsafe.getObjectVolatile(Person.names, offset + si * 0));
//
ConcurrentHashMap<String,String> cHashMap = new ConcurrentHashMap<String, String> ();
cHashMap.put("biozzo", "nice~");
}
static class Person{
private static int i = 0;
static Field f;
static String[] names = new String[]{
"biozzo","kevin","can"};
private static Unsafe unsafe;
static {
try {
f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
unsafe = (Unsafe) f.get(null);
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
}
static Unsafe getUnsafe(){
return unsafe;
}
}
}
直接通过反射拿到属性就可以了,这个小案例展示了一个通过使用Unsafe得到数组值得方法,就像是寻址一样,si是步长,offset是偏移量,通过这样就可以拿到数组中的值。
我们再来看ConcurrentHashMap的构造方法:
public ConcurrentHashMap(int initialCapacity,
float loadFactor, int concurrencyLevel) {
if (!(loadFactor > 0) || initialCapacity < 0 || concurrencyLevel <= 0)
throw new IllegalArgumentException();
if (concurrencyLevel > MAX_SEGMENTS)
concurrencyLevel = MAX_SEGMENTS;
// Find power-of-two sizes best matching arguments
int sshift = 0;
int ssize = 1;
while (ssize < concurrencyLevel) {
++sshift;
ssize <<= 1;
}
this.segmentShift = 32 - sshift;
this.segmentMask = ssize - 1;
if (initialCapacity > MAXIMUM_CAPACITY)
initialCapacity = MAXIMUM_CAPACITY;
int c = initialCapacity / ssize;
if (c * ssize < initialCapacity)
++c;
int cap = MIN_SEGMENT_TABLE_CAPACITY;
while (cap < c)
cap <<= 1;
// create segments and segments[0]
Segment<K,V> s0 =
new Segment<K,V>(loadFactor, (int)(cap * loadFactor),
(HashEntry<K,V>[])new HashEntry[cap]);
Seg