n("Unsafe.ARRAY_FLOAT_INDEX_SCALE=" + Unsafe.ARRAY_FLOAT_INDEX_SCALE);
System.out.println("Unsafe.ARRAY_DOUBLE_BASE_OFFSET=" + Unsafe.ARRAY_DOUBLE_BASE_OFFSET);
System.out.println("Unsafe.ARRAY_DOUBLE_INDEX_SCALE=" + Unsafe.ARRAY_DOUBLE_INDEX_SCALE);
System.out.println("Unsafe.ARRAY_OBJECT_BASE_OFFSET=" + Unsafe.ARRAY_OBJECT_BASE_OFFSET);
System.out.println("Unsafe.ARRAY_OBJECT_INDEX_SCALE=" + Unsafe.ARRAY_OBJECT_INDEX_SCALE);
System.out.println("------------------------------");
// 基本数据数组类型操作
int[] array = new int[] {11, 22, 33};
/*
改变最后一个元素的值,地址的算法就是:基础地址+偏移量,这个偏移量就是类型占用的大小*位置,Unsafe.ARRAY_INT_BASE_OFFSET + (array.length - 1) * Unsafe.ARRAY_INT_INDEX_SCALE
*/
System.out.println("before put array[2]=" + array[2]);
unsafe.putInt(array, (long)Unsafe.ARRAY_INT_BASE_OFFSET + (array.length - 1) * Unsafe.ARRAY_INT_INDEX_SCALE,
100);
// 获取最后一个元素的值
System.out.println("after put array[2]=" + array[2]);
// 也可以这么获取,使用基础地址+偏移量的方式
System.out.println("after put array[2]=" + unsafe.getInt(array,
(long)Unsafe.ARRAY_INT_BASE_OFFSET + (array.length - 1) * Unsafe.ARRAY_INT_INDEX_SCALE));
System.out.println("-------------------");
// Object类型数组操作
Cat[] cats = {new Cat("cat1", 1), new Cat("cat2", 2), new Cat("cat3", 3)};
System.out.println("before put cats[2]=" + cats[2]);
unsafe.putObject(cats,
(long)Unsafe.ARRAY_OBJECT_BASE_OFFSET + (cats.length - 1) * Unsafe.ARRAY_OBJECT_INDEX_SCALE,
new Cat("newcat", 10000));
// 获取最后一个元素的值
System.out.println("after put cats[2]=" + cats[2]);
// 也可以这么获取,使用基础地址+偏移量的方式
System.out.println("after put cats[2]=" + unsafe.getObject(cats,
(long)Unsafe.ARRAY_OBJECT_BASE_OFFSET + (cats.length - 1) * Unsafe.ARRAY_OBJECT_INDEX_SCALE));
System.out.println("-------------------");
}
输出:
Unsafe.ARRAY_BOOLEAN_BASE_OFFSET=16
Unsafe.ARRAY_BOOLEAN_INDEX_SCALE=1
Unsafe.ARRAY_BYTE_BASE_OFFSET=16
Unsafe.ARRAY_BYTE_INDEX_SCALE=1
Unsafe.ARRAY_SHORT_BASE_OFFSET=16
Unsafe.ARRAY_SHORT_INDEX_SCALE=2
Unsafe.ARRAY_CHAR_BASE_OFFSET=16
Unsafe.ARRAY_CHAR_INDEX_SCALE=2
Unsafe.ARRAY_INT_BASE_OFFSET=16
Unsafe.ARRAY_INT_INDEX_SCALE=4
Unsafe.ARRAY_LONG_BASE_OFFSET=16
Unsafe.ARRAY_LONG_INDEX_SCALE=8
Unsafe.ARRAY_FLOAT_BASE_OFFSET=16
Unsafe.ARRAY_FLOAT_INDEX_SCALE=4
Unsafe.ARRAY_DOUBLE_BASE_OFFSET=16
Unsafe.ARRAY_DOUBLE_INDEX_SCALE=8
Unsafe.ARRAY_OBJECT_BASE_OFFSET=16
Unsafe.ARRAY_OBJECT_INDEX_SCALE=4
------------------------------
before put array[2]=33
after put array[2]=100
after put array[2]=100
-------------------
static...
before put cats[2]=Cat{name='cat3', speed=3}
after put cats[2]=Cat{name='newcat', speed=10000}
after put cats[2]=Cat{name='newcat', speed=10000}
-------------------
Tips:
如果操作的元素位置没有在数组范围内的话,put和get操作不会异常,都会成功,因为这是内存操作,使用的是基础地址+偏移量,但是并没有改变原始数组的大小,put后可以获取相应位置的内存数据,在没有put前调用get则获取的是数据类型的默认值。
CAS
比较并交换(Compare And Swap),在jvm里是一个原子操作,先获取内存的值,然后判断内存值和预期值是否相同,相同则更新为新值表示操作成功,不同则直接返回false,表明操作失败。java里的JUC包下很多队列或者锁都采用了这种实现方式。
//每次都从主内存获取var1对象var2偏移量的long值
public native long getLong