強いsunを手に入れるmisc.Unsafeインスタンス
java.util.concurrentパッケージの多くのクラスの実装はハードウェアベースのCASアルゴリズムを用いており、synchronizedキーを使用して同時制御を行うことはなく、関連するソースコードを見ると最後にクラスを指していることがわかります.これがSUN未オープンソースのsunです.misc.Unsafeのクラスは、クラスのロードメカニズムに関連する強力な機能を持ち、そのインスタンスは一般的に取得できません.JVMがrt.jarをロードするときにクラスがロードされ、初期化されているため、反射のメカニズムが可能です.じょうふごう
テストクラスで遊ぶ
テストケースの実行
結果
2010-12-23 16:59:56:352 [INFO] com.api.UnsafeTest.main(UnsafeTest.java:29) - fieldName:fieldOffset
2010-12-23 16:59:56:368 [INFO] com.api.UnsafeTest.main(UnsafeTest.java:32) - byteParam:36
2010-12-23 16:59:56:368 [INFO] com.api.UnsafeTest.main(UnsafeTest.java:32) - charParam:32
2010-12-23 16:59:56:368 [INFO] com.api.UnsafeTest.main(UnsafeTest.java:32) - shorteParam:34
2010-12-23 16:59:56:368 [INFO] com.api.UnsafeTest.main(UnsafeTest.java:32) - intParam:24
2010-12-23 16:59:56:368 [INFO] com.api.UnsafeTest.main(UnsafeTest.java:32) - intParam2:28
2010-12-23 16:59:56:368 [INFO] com.api.UnsafeTest.main(UnsafeTest.java:32) - longParam:8
2010-12-23 16:59:56:368 [INFO] com.api.UnsafeTest.main(UnsafeTest.java:32) - doubleParam:16
2010-12-23 16:59:56:368 [INFO] com.api.UnsafeTest.main(UnsafeTest.java:32) - strParam:40
2010-12-23 16:59:56:368 [INFO] com.api.UnsafeTest.main(UnsafeTest.java:32) - strParam2:44
2010-12-23 16:59:56:368 [INFO] com.api.UnsafeTest.main(UnsafeTest.java:40) - true
2010-12-23 16:59:56:368 [INFO] com.api.UnsafeTest.main(UnsafeTest.java:42) - false
2010-12-23 16:59:56:368 [INFO] com.api.UnsafeTest.main(UnsafeTest.java:44) - true
注:j 2 sdk 1.4.2_09中compareAndSwapIntは提供していません.1.5以上でbeaのjrockit 81 sp 6があるようです.142_10にあり、jrockitが使われています.vmパッケージのMemory
/*
* Copyright 2010, the original author or authors. All rights reserved.
*/
package com.api;
import java.lang.reflect.Field;
import org.apache.log4j.Logger;
import sun.misc.Unsafe;
/**
* {@link sun.misc.Unsafe} <br>
* rt.jar
*
* <pre>
*
* package sun.misc;
*
* import java.lang.reflect.Field;
* import java.lang.reflect.Modifier;
* import java.security.ProtectionDomain;
* import sun.reflect.Reflection;
*
* public final class Unsafe
* {
* private static final Unsafe theUnsafe;
* public static final int INVALID_FIELD_OFFSET = -1;
*
* private static native void registerNatives();
*
* public static Unsafe getUnsafe()
* {
* Class localClass = Reflection.getCallerClass(2);
* if (localClass.getClassLoader() != null)
* throw new SecurityException("Unsafe");
* return theUnsafe;
* }
* static
* {
* registerNatives();
*
* theUnsafe = new Unsafe();
* }
* ..........................
* </pre>
*
* @author <a href="mailto:[email protected]">xiao jiang</a>
* @version %I%, %G%
* @history 2010-12-23
*/
public class UnsafeSupport {
private static Logger log = Logger.getLogger(UnsafeSupport.class);
private static Unsafe unsafe;
static {
Field field;
try {
// Unsafe
field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
// ,Unsafe JVM rt.jar
unsafe = (Unsafe) field.get(null);
} catch (Exception e) {
log.error("Get Unsafe instance occur error", e);
}
}
/**
* {@link Unsafe }
*/
public static Unsafe getInstance() {
return unsafe;
}
public static void main(String[] args) {
}
}
テストクラスで遊ぶ
/*
* Copyright 2010, the original author or authors. All rights reserved.
*/
package com.api;
/**
*
*
* @author <a href="mailto:[email protected]">xiao jiang</a>
* @version %I%, %G%
* @history 2010-12-23
*/
public class AnalyzedTarget {
private byte byteParam;
private char charParam;
private short shorteParam;
private int intParam;
private int intParam2;
private long longParam;
private double doubleParam;
private String strParam;
private String strParam2;
}
テストケースの実行
/*
*Copyright 2010, the original author or authors. All rights reserved.
*/
package com.api;
import java.lang.reflect.Field;
import org.apache.log4j.Logger;
import sun.misc.Unsafe;
/**
* rt.jar Unsafe
*
* @author <a href="mailto:[email protected]">xiao jiang</a>
* @version %I%, %G%
* @history 2010-12-23
*/
public class UnsafeTest {
private static Logger log = Logger.getLogger(UnsafeTest.class);
public static void main(String[] args) {
Unsafe unsafe = UnsafeSupport.getInstance();
//
// unsafe.allocateMemory(1000000000l);
Class clazz = AnalyzedTarget.class;
Field[] fields = clazz.getDeclaredFields();
log.info("fieldName:fieldOffset");
// ,
for (Field f : fields) {
log.info(f.getName() + ":" + unsafe.objectFieldOffset(f));
}
// arg0, arg1, arg2, arg3 , , ,
// unsafe.compareAndSwapInt(arg0, arg1, arg2, arg3)
AnalyzedTarget target = new AnalyzedTarget();
// ,intParam
long intParamOffset = 24;
// , true , CAS ,
log.info(unsafe.compareAndSwapInt(target, intParamOffset, 0, 3));
//
log.info(unsafe.compareAndSwapInt(target, intParamOffset, 0, 10));
// , 3, ture
log.info(unsafe.compareAndSwapInt(target, intParamOffset, 3, 10));
}
}
結果
2010-12-23 16:59:56:352 [INFO] com.api.UnsafeTest.main(UnsafeTest.java:29) - fieldName:fieldOffset
2010-12-23 16:59:56:368 [INFO] com.api.UnsafeTest.main(UnsafeTest.java:32) - byteParam:36
2010-12-23 16:59:56:368 [INFO] com.api.UnsafeTest.main(UnsafeTest.java:32) - charParam:32
2010-12-23 16:59:56:368 [INFO] com.api.UnsafeTest.main(UnsafeTest.java:32) - shorteParam:34
2010-12-23 16:59:56:368 [INFO] com.api.UnsafeTest.main(UnsafeTest.java:32) - intParam:24
2010-12-23 16:59:56:368 [INFO] com.api.UnsafeTest.main(UnsafeTest.java:32) - intParam2:28
2010-12-23 16:59:56:368 [INFO] com.api.UnsafeTest.main(UnsafeTest.java:32) - longParam:8
2010-12-23 16:59:56:368 [INFO] com.api.UnsafeTest.main(UnsafeTest.java:32) - doubleParam:16
2010-12-23 16:59:56:368 [INFO] com.api.UnsafeTest.main(UnsafeTest.java:32) - strParam:40
2010-12-23 16:59:56:368 [INFO] com.api.UnsafeTest.main(UnsafeTest.java:32) - strParam2:44
2010-12-23 16:59:56:368 [INFO] com.api.UnsafeTest.main(UnsafeTest.java:40) - true
2010-12-23 16:59:56:368 [INFO] com.api.UnsafeTest.main(UnsafeTest.java:42) - false
2010-12-23 16:59:56:368 [INFO] com.api.UnsafeTest.main(UnsafeTest.java:44) - true
注:j 2 sdk 1.4.2_09中compareAndSwapIntは提供していません.1.5以上でbeaのjrockit 81 sp 6があるようです.142_10にあり、jrockitが使われています.vmパッケージのMemory