Package nginx.clojure

Source Code of nginx.clojure.HackUtils

/**
*  Copyright (C) Zhang,Yuexiang (xfeep)
*
*/
package nginx.clojure;

import static nginx.clojure.MiniConstants.STRING_CHAR_ARRAY_OFFSET;

import java.lang.ref.Reference;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
import java.nio.charset.CodingErrorAction;
import java.security.AccessControlContext;

import sun.misc.Unsafe;
import sun.nio.cs.ThreadLocalCoders;

public class HackUtils {

    private static final long threadLocalsOffset;
    private static final long inheritableThreadLocalsOffset;
    private static final long contextClassLoaderOffset;
    private static final long inheritedAccessControlContextOffset;
    private static final Method createInheritedMap;
    private static final Class threadLocalMapClass;
   
  private static final long  threadLocalMapTableFieldOffset;// = UNSAFE.objectFieldOffset(threadLocalMapTableField);
  private static final long  threadLocalMapSizeFieldOffset;// = UNSAFE.objectFieldOffset(threadLocalMapSizeField);
  private static final long  threadLocalMapThresholdFieldOffset;// = UNSAFE.objectFieldOffset(threadLocalMapThresholdField);
   
    private static final Class threadLocalMapEntryClass;
  private static final long  threadLocalMapEntryValueFieldOffset;
  private static final long  threadLocalMapEntryReferentFieldOffset;
  private static final long threadLocalMapEntryQueueFieldOffset;
 
 
  /*use it carefully!!*/
  public static Unsafe UNSAFE = null;
 

  public HackUtils() {
  }
 
  public static void initUnsafe() {
    if (UNSAFE != null) {
      return;
    }
      try{
          Field field = Unsafe.class.getDeclaredField("theUnsafe");
          field.setAccessible(true);
          UNSAFE = (Unsafe)field.get(null);
      }
      catch (Exception e){
          throw new RuntimeException(e);
      }
  }
 
 


    static {
      initUnsafe();
        try {
         
            threadLocalsOffset = UNSAFE.objectFieldOffset(Thread.class.getDeclaredField("threadLocals"));
            inheritableThreadLocalsOffset = UNSAFE.objectFieldOffset(Thread.class.getDeclaredField("inheritableThreadLocals"));
            contextClassLoaderOffset = UNSAFE.objectFieldOffset(Thread.class.getDeclaredField("contextClassLoader"));

            long _inheritedAccessControlContextOffset = -1;
            try {
                _inheritedAccessControlContextOffset = UNSAFE.objectFieldOffset(Thread.class.getDeclaredField("inheritedAccessControlContext"));
            } catch (NoSuchFieldException e) {
            }
            inheritedAccessControlContextOffset = _inheritedAccessControlContextOffset;

            threadLocalMapClass = Class.forName("java.lang.ThreadLocal$ThreadLocalMap");
            createInheritedMap = ThreadLocal.class.getDeclaredMethod("createInheritedMap", threadLocalMapClass);
            createInheritedMap.setAccessible(true);
           
            threadLocalMapTableFieldOffset = UNSAFE.objectFieldOffset(threadLocalMapClass.getDeclaredField("table"));
          threadLocalMapSizeFieldOffset = UNSAFE.objectFieldOffset(threadLocalMapClass.getDeclaredField("size"));
          threadLocalMapThresholdFieldOffset = UNSAFE.objectFieldOffset(threadLocalMapClass.getDeclaredField("threshold"));
         
            threadLocalMapEntryClass = Class.forName("java.lang.ThreadLocal$ThreadLocalMap$Entry");
            threadLocalMapEntryValueFieldOffset = UNSAFE.objectFieldOffset(threadLocalMapEntryClass.getDeclaredField("value"));
            threadLocalMapEntryReferentFieldOffset = UNSAFE.objectFieldOffset(Reference.class.getDeclaredField("referent"));
            threadLocalMapEntryQueueFieldOffset = UNSAFE.objectFieldOffset(Reference.class.getDeclaredField("queue"));
           
        } catch (Exception ex) {
            throw new AssertionError(ex);
        }
    }

    public static Object getThreadLocals(Thread thread) {
        return UNSAFE.getObject(thread, threadLocalsOffset);
    }

    public static void setThreadLocals(Thread thread, Object threadLocals) {
        UNSAFE.putObject(thread, threadLocalsOffset, threadLocals);
    }

    public static Object getInheritableThreadLocals(Thread thread) {
        return UNSAFE.getObject(thread, inheritableThreadLocalsOffset);
    }

    public static void setInheritablehreadLocals(Thread thread, Object inheritableThreadLocals) {
        UNSAFE.putObject(thread, inheritableThreadLocalsOffset, inheritableThreadLocals);
    }

    public static Object createInheritedMap(Object inheritableThreadLocals) {
      return cloneThreadLocalMap(inheritableThreadLocals);
    }

    public static Object cloneThreadLocalMap(Object o) {
        try {
            Object clone = UNSAFE.allocateInstance(threadLocalMapClass);
            Object origTable =  UNSAFE.getObject(o, threadLocalMapTableFieldOffset);
           
            int len = Array.getLength(origTable);
            Object tableClone = Array.newInstance(threadLocalMapEntryClass, len);
            for (int i = 0; i < len; i++) {
                Object entry = Array.get(origTable, i);
                if (entry != null)
                    Array.set(tableClone, i, cloneThreadLocalMapEntry(entry));
            }
           
            UNSAFE.putObject(clone, threadLocalMapTableFieldOffset, tableClone);
            UNSAFE.putInt(clone, threadLocalMapSizeFieldOffset, UNSAFE.getInt(o, threadLocalMapSizeFieldOffset));
            UNSAFE.putInt(clone, threadLocalMapThresholdFieldOffset, UNSAFE.getInt(o, threadLocalMapThresholdFieldOffset));
           
            return clone;
        } catch (Exception ex) {
            throw new AssertionError("can not cloneThreadLocalMap", ex);
        }
    }
   

    private static Object cloneThreadLocalMapEntry(Object entry) {
        try {
          Object clone = UNSAFE.allocateInstance(threadLocalMapEntryClass);
          UNSAFE.putObject(clone, threadLocalMapEntryReferentFieldOffset, UNSAFE.getObject(entry, threadLocalMapEntryReferentFieldOffset));
          UNSAFE.putObject(clone, threadLocalMapEntryValueFieldOffset, UNSAFE.getObject(entry, threadLocalMapEntryValueFieldOffset));
          UNSAFE.putObject(clone, threadLocalMapEntryQueueFieldOffset, UNSAFE.getObject(entry, threadLocalMapEntryQueueFieldOffset));
          return clone;
        } catch (Exception e) {
            throw new AssertionError("can not cloneThreadLocalMapEntry", e);
        }
    }


    public static ClassLoader getContextClassLoader(Thread thread) {
        return (ClassLoader) UNSAFE.getObject(thread, contextClassLoaderOffset);
    }

    public static void setContextClassLoader(Thread thread, ClassLoader classLoader) {
        UNSAFE.putObject(thread, contextClassLoaderOffset, classLoader);
    }

    public static AccessControlContext getInheritedAccessControlContext(Thread thread) {
        if (inheritedAccessControlContextOffset < 0)
            return null;
        return (AccessControlContext) UNSAFE.getObject(thread, inheritedAccessControlContextOffset);
    }

    public static void setInheritedAccessControlContext(Thread thread, AccessControlContext accessControlContext) {
        if (inheritedAccessControlContextOffset >= 0)
            UNSAFE.putObject(thread, inheritedAccessControlContextOffset, accessControlContext);
    }
   
    public static ByteBuffer encode(String s, Charset cs, ByteBuffer bb)  {
    CharsetEncoder ce =  ThreadLocalCoders.encoderFor(cs)
        .onMalformedInput(CodingErrorAction.REPLACE)
        .onUnmappableCharacter(CodingErrorAction.REPLACE);
    CharBuffer cb = CharBuffer.wrap((char[])UNSAFE.getObject(s, STRING_CHAR_ARRAY_OFFSET));
    ce.reset();
    CoderResult rt = ce.encode(cb, bb, true);
    if (rt == CoderResult.OVERFLOW) {
      bb.flip();
      ByteBuffer lbb = ByteBuffer.allocate((int)(s.length() * (double)ce.maxBytesPerChar()));
      lbb.put(bb);
      bb = lbb;
      rt = ce.encode(cb, bb, true);
    }
    if (rt != CoderResult.UNDERFLOW) {
      throw new RuntimeException(rt.toString());
    }
    rt = ce.flush(bb);
    if (rt != CoderResult.UNDERFLOW) {
      throw new RuntimeException(rt.toString());
    }
    bb.flip();
    return bb;
    }
   
    public static String decode(ByteBuffer bb, Charset cs, CharBuffer cb)  {
      CharsetDecoder de = ThreadLocalCoders.decoderFor(cs)
          .onMalformedInput(CodingErrorAction.REPLACE)
        .onUnmappableCharacter(CodingErrorAction.REPLACE);
      de.reset();
      int len = bb.remaining();
      CoderResult rt = de.decode(bb, cb, true);
      if (rt == CoderResult.OVERFLOW) {
        cb.flip();
        CharBuffer lcb = CharBuffer.allocate((int)(len * (double)de.maxCharsPerByte()));
        lcb.put(cb);
        cb = lcb;
        rt = de.decode(bb, cb, true);
      }
     
    if (rt != CoderResult.UNDERFLOW) {
      throw new RuntimeException(rt.toString());
    }
    rt = de.flush(cb);
    if (rt != CoderResult.UNDERFLOW) {
      throw new RuntimeException(rt.toString());
    }
    cb.flip();
    return cb.toString();
    }
   

}
TOP

Related Classes of nginx.clojure.HackUtils

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.