¿Cuál es la clase insegura?
Java fue diseñado originalmente como un entorno controlado seguro. A pesar de esto, Java Hotspot todavía incluye una "puerta trasera" que proporciona algunas operaciones de bajo nivel que pueden manipular directamente la memoria y los hilos. Esta clase de puerta trasera, Sun.misc.unsafe, es ampliamente utilizada en sus propios paquetes por JDK, como Java.nio y Java.util.concurrent. Sin embargo, esta puerta trasera no se recomienda en entornos de producción en absoluto. Porque esta API es muy insegura, no ligera e inestable. Esta clase insegura proporciona una vista de la estructura interna del punto de acceso JVM y puede modificarse. A veces se puede usar para aprender la estructura interna de la máquina virtual sin depuración de C ++, y a veces se puede utilizar como herramientas de monitoreo y desarrollo de rendimiento.
introducción
Recientemente, estaba mirando el código fuente de los paquetes concurrentes de Java y descubrí la clase mágica insegura. Lo estudié cuidadosamente y lo compartí contigo aquí.
La clase insegura está debajo del paquete Sun.Misc y no pertenece al estándar Java. Sin embargo, muchas bibliotecas básicas de clase Java, incluidas algunas bibliotecas de desarrollo de alto rendimiento ampliamente utilizadas, se desarrollan en base a una clase insegura, como Netty, Cassandra, Hadoop, Kafka, etc. La clase insegura juega un gran papel en la mejora de la eficiencia de la operación de Java y en la mejora de las capacidades de operación subyacentes del lenguaje Java.
La clase insegura le da a Java la capacidad de operar espacio de memoria como punteros en el lenguaje C, y también trae problemas de puntero. El uso excesivo de la clase insegura aumentará las posibilidades de errores, por lo que Java no recomienda que se use, y casi no hay documentación oficial. Oracle planea eliminar la clase insegura de Java 9, y si ese es el caso, sería demasiado grande.
Por lo general, es mejor no usar la clase insegura a menos que tenga un propósito claro y también tenga una comprensión profunda de ella. Para usar la clase insegura, debe usar algunos métodos difíciles. La clase insegura usa un patrón singleton y debe obtenerse a través de un método estático getunSafe (). Sin embargo, la clase insegura lo ha restringido. Si es una llamada normal, lanzará una excepción de SecurityException; Solo la clase cargada por el cargador de clase principal puede llamar a este método. El código fuente es el siguiente:
public static inseguro getunSafe () {class var0 = refles.getCallerClass (); if (! vm.issystemdomainloader (var0.getClassLoader ())) {tire nueva seguridadxception ("insegura"); } else {return theUnSafe; }}También hay algunas formas de cargar el código de usuario utilizando el cargador de clase principal, como configurar el parámetro BootClassPath. Pero la forma más simple es usar Java Reflection, como sigue:
Campo f = unsafe.class.getDeclaredfield ("TheUnSafe"); F.SetAccessible (verdadero); Inseguro inseguro = (inseguro) f.get (nulo);Después de obtener la instancia insegura, podemos hacer lo que queramos. La clase insegura proporciona las siguientes funciones:
1. Gestión de memoria. Incluyendo asignar memoria, liberar memoria, etc.
Esta parte incluye Allocatememory (Allocatememory), RealLocAtEmemory (RealLocAtEmemory), CopyMemory (Copy Memory), FreeMeMemory (Free Memory), GetAddress (getget Memory Address), direcciones, pagos, getINT (obtenga el entero señalado a la dirección de la memoria), getintvolatile (obtenga la dirección de la memoria y la memoria. semántica), Putint (escriba el entero en la dirección de memoria especificada), PutIntVolatile (escriba el entero en la dirección de memoria especificada y admite semántico volátil), PutorderedInt (escriba el entero en la dirección de memoria especificada, métodos ordenados o retrasados). getxxx y putxxx contienen varios tipos básicos de operaciones.
Usando el método CopyMemory, podemos implementar un método general de copia de objeto sin implementar el método clon para cada objeto. Por supuesto, este método general solo puede lograr una copia superficial del objeto.
2. Instanciación de objetos no convencionales.
El método thlockInstance () proporciona otra forma de crear una instancia. Por lo general, podemos instanciar objetos con nuevo o reflexión. Utilice el método AllOCTEInStance () para generar directamente instancias de objetos sin llamar a constructores y otros métodos de inicialización.
Esto es útil al deserializar objetos, permitiendo la reconstrucción y establecer campos finales sin llamar a los constructores.
3. Clases de operación, objetos y variables.
Esta parte incluye staticfieldoffset (desplazamiento de dominio estático), definido (clase de definición), DefeAnyonyMlass (definición de clase anónima), EnsureClassinicialized (garantizar la inicialización de la clase), ObjectFieldOffset (Opjed Domain Offset) y otros métodos.
A través de estos métodos, podemos obtener el puntero del objeto. Al compensar el puntero, no solo podemos modificar directamente los datos señalados por el puntero (incluso si son privados), sino que incluso podemos encontrar objetos que el JVM ya ha considerado basura y se puede reciclar.
4. Operación de matriz.
Esta parte incluye ArrayBaseffset (obtiene la dirección de desplazamiento del primer elemento de la matriz), ArrayIndexscale (obtiene la dirección de incremento del elemento en la matriz), etc. ArrayBaseOffset se usa junto con ArrayInCale, y puede localizar la posición de cada elemento en la matriz en la memoria.
Dado que el valor de matriz máximo de Java es entero.max_value, el método de asignación de memoria de la clase insegura se puede utilizar para implementar matrices súper grandes. De hecho, dichos datos pueden considerarse una matriz C, por lo que debe prestar atención a la liberación de la memoria en el momento adecuado.
5. Sincronización de múltiples hilos. Incluyendo mecanismo de bloqueo, operación CAS, etc.
Esta parte incluye Monitorenter, TryMonitoreNer, Monitorexit, CompareandsWapint, CompareandsWap y otros métodos.
Entre ellos, MonitorEenter, TryMonitorenter y Monitorexit se han marcado como desaprobados y no se recomiendan.
La operación CAS de la clase insegura se puede usar más, y proporciona una nueva solución para el mecanismo de bloqueo de Java. Por ejemplo, AtomicInteger y otras clases se implementan a través de este método. El método de comparación con comparación es atómico, lo que puede evitar mecanismos de bloqueo pesados y mejorar la eficiencia del código. Este es un bloqueo optimista, que generalmente se cree que en la mayoría de los casos no hay condición de raza, y si la operación falla, continuará intentándose nuevamente hasta que tenga éxito.
6. suspender y restaurar.
Esta parte incluye Park, Unpark y otros métodos.
Suspender un hilo a través del método del parque. Después de llamar a Park, el hilo se bloqueará hasta que ocurra el tiempo de espera o la interrupción. Unpark puede terminar un hilo pendiente para restaurarlo a la normalidad. La operación de suspensión de los subprocesos en todo el marco de concurrencia está encapsulado en la clase Locksupport. Existen varias versiones de los métodos de paquete en la clase Locksupport, pero al final, se llama al método Unsafe.Park ().
7. Barrera de memoria.
Esta parte incluye LoadFence, StoreFence, Fullfence y otros métodos. Esto se introduce recientemente en Java 8 para definir las barreras de memoria para evitar el reordenamiento de código.
LoadFence () significa que todas las operaciones de carga antes del método se completan antes de la barrera de memoria. Del mismo modo, StoreFence () significa que todas las operaciones de la tienda antes de que este método se complete antes de la barrera de memoria. FullFence () significa que todas las operaciones de carga y almacenamiento antes del método se completan antes de la barrera de memoria.
Resumir
Lo anterior es todo el contenido de este artículo. Espero que el contenido de este artículo tenga cierto valor de referencia para el estudio o el trabajo de todos. Si tiene alguna pregunta, puede dejar un mensaje para comunicarse. Gracias por su apoyo a Wulin.com.