Aprendizaje inseguro

Inseguro

Unfase nos proporciona acceso al mecanismo subyacente, que solo es utilizado por la biblioteca de clases de Java Core.

Por lo tanto, los programas de usuario comunes no pueden obtener directamente sus instancias, y el método de construcción inseguro es privado, pero podemos obtenerlos a través de la reflexión.

1. Sea inseguro

Inseguro tiene un método getUnsafe () para obtener una instancia:

 @CallerSensitive
    public static Unsafe getUnsafe() {
        Class var0 = Reflection.getCallerClass();
        if (!VM.isSystemDomainLoader(var0.getClassLoader())) {
            throw new SecurityException("Unsafe");
        } else {
            return theUnsafe;
        }
    }

Devuelve inseguro, private static final Unsafe theUnsafe;por lo que podemos obtener esta instancia por reflexión:

public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        Unsafe unsafe = getUnsafe();
        System.out.println(unsafe);
    }

    /**
     * 获取Unsafe实例
     * @return
     * @throws NoSuchFieldException
     * @throws IllegalAccessException
     */
    public static Unsafe getUnsafe() throws NoSuchFieldException,IllegalAccessException {
        Field field = Unsafe.class.getDeclaredField("theUnsafe");
        field.setAccessible(true);
        return (Unsafe)field.get(null);
    }

2. Objeto de creación inseguro

public class UnSafeDemo {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, InstantiationException {
        //2.创建对象
        newInstance();
    }


    public static void newInstance() throws NoSuchFieldException, IllegalAccessException, InstantiationException {
        Unsafe unsafe = getUnsafe();
        Book book = (Book) unsafe.allocateInstance(Book.class);
        System.out.println(book.getName()+"\t"+book.getPrice());
    }
}
class Book {
    private String name;
    private Integer price;

    public Book() {
        name="三国演义";
        price=77;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getPrice() {
        return price;
    }

    public void setPrice(Integer price) {
        this.price = price;
    }
}

El resultado de la impresión es nulo nulo porque:

El método allocateInstance se usa para crear una instancia de una clase, pero no se llama al constructor de esta instancia. Si la clase no se ha inicializado, inicialice la clase.

3. Operación de memoria directa

// 分配内存(堆外)
public native long allocateMemory(long var1);
// 重新分配内存
public native long reallocateMemory(long var1, long var3);
// 内存初始化
public native void setMemory(long var1, long var3, byte var5);
// 内存复制
public native void copyMemory(Object var1, long var2, Object var4, long var5, long var7);
// 清除内存
public native void freeMemory(long var1);

Podemos llamar a un allocateMemorymétodo para asignar memoria local fuera del montón para el proceso, pero debido a que esta parte de la memoria no está bajo la jurisdicción de la JVM, necesitamos un freeMemorymétodo para reciclar

4. Operación CAS

En JUC se utilizan muchas operaciones CAS, que son la base del paquete juc. Inseguro proporciona int, long y CAS, a saber Compare and Swap, que es un algoritmo sin bloqueo. Si es un bloqueo, es un bloqueo optimista. Solo se actualizará cuando se manipulen los datos. , Es más eficiente que el procesamiento de bloqueo pesimista.

Parámetro 1: el objeto a modificar

Parámetro 2: Offset

Parámetro 3: valor esperado oldValue

Parámetro 4: el valor actualizado newValue

public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5);

public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);

public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6);

5. Excepción lanzada

ThrowException usando Unsafe no necesita ser lanzado en el método:

unsafe.throwException(new IllegalArgumentException());

6. Hilo relacionado

public native void unpark(Object var1);

public native void park(boolean var1, long var2);

public native void monitorEnter(Object var1);

public native void monitorExit(Object var1);

public native boolean tryMonitorEnter(Object var1);

Estacionar y anular se utilizan en LockSupport:

 public static void park(Object blocker) {
        Thread t = Thread.currentThread();
        setBlocker(t, blocker);
        UNSAFE.park(false, 0L);
        setBlocker(t, null);
    }

Cuando el hilo necesite bloquearse, llame al método park (). Cuando el hilo necesite continuar ejecutándose, llame al método
unpark () monitorEnter: para
bloquear el objeto, que debe monitorExitser desbloqueado por el método. Reentrante
Añadido synchronizedgenerada clave archivos de código de bytes del segmento de código serán más monitorentery monitorexitdos instrucciones

7. putXXX 和 getXXX

Tome int como ejemplo:

  • getInt

    • El primer parámetro: leer el objeto
    • El segundo parámetro: dirección de desplazamiento de memoria
  • putInt

    • El primer parámetro: modificar el objeto
    • El segundo parámetro: dirección de desplazamiento de memoria
    • El tercer parámetro: el nuevo valor a modificar
public native int getInt(Object var1, long var2);

public native void putInt(Object var1, long var2, int var4);
 public static void getAndPut() throws InstantiationException, NoSuchFieldException {
        Unsafe unsafe = getUnsafe();
        Book book =new Book();
        Field field = book.getClass().getDeclaredField("name");
        unsafe.putObject(book,unsafe.objectFieldOffset(field),"新三国演义");
        System.out.println(book.getName());//新三国演义
    }

unsafe.objectFieldOffset (campo): obtenga la dirección de desplazamiento de memoria del campo correspondiente

8. relacionado volátil

getXXXVolatile : lea el valor del objeto con la dirección de desplazamiento de memoria var2 en forma de volátil.

putXXXVolatile : modifica el valor del objeto con la dirección de desplazamiento de memoria var2 en forma de volátil

Dado que se utiliza volátil, significa que la operación garantiza el orden y la visibilidad.

public native Object getObjectVolatile(Object var1, long var2);

public native void putObjectVolatile(Object var1, long var2, Object var4);

9.orden relacionado

 public native void putOrderedObject(Object var1, long var2, Object var4);

    public native void putOrderedInt(Object var1, long var2, int var4);

    public native void putOrderedLong(Object var1, long var2, long var4);

Asegure una escritura y modificación ordenadas. Solo el pedido está garantizado. Por lo tanto, la visibilidad y la atomicidad no están garantizadas.

Publicado 75 artículos originales · alabanza ganado 13 · vistas 8369

Supongo que te gusta

Origin blog.csdn.net/weixin_43696529/article/details/105060172
Recomendado
Clasificación