強いsunを手に入れるmisc.Unsafeインスタンス


java.util.concurrentパッケージの多くのクラスの実装はハードウェアベースのCASアルゴリズムを用いており、synchronizedキーを使用して同時制御を行うことはなく、関連するソースコードを見ると最後にクラスを指していることがわかります.これがSUN未オープンソースのsunです.misc.Unsafeのクラスは、クラスのロードメカニズムに関連する強力な機能を持ち、そのインスタンスは一般的に取得できません.JVMがrt.jarをロードするときにクラスがロードされ、初期化されているため、反射のメカニズムが可能です.じょうふごう
 
/*
 * 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(&quot;Unsafe&quot;);
 *  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