Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What are the knowledge points of Java Unsafe?

2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article introduces the relevant knowledge of "what are the knowledge points of Java Unsafe". In the operation of actual cases, many people will encounter such a dilemma. Next, let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!

Sun.misc.Unsafe

Function: can be used to read and write data at any memory address, supporting some CAS atomic operations

Java was originally designed as a secure, controlled environment. Nevertheless, HotSpot includes a backdoor sun.misc.Unsafe that provides some low-level operations that can directly manipulate memory and threads. Unsafe is widely used by JDK in implementations such as java.nio and concurrency packages. This unsafe class provides a way to observe the internal structure of HotSpot JVM and modify it, but it is not recommended in production environments.

Get Unsafe instance

The Unsafe object cannot be obtained directly through new Unsafe () or by calling Unsafe.getUnsafe () for the following reasons:

Cannot new Unsafe () directly because Unsafe is designed as a singleton pattern and the constructor is private

Cannot be obtained by calling Unsafe.getUnsafe () because getUnsafe is designed to be loaded only from the boot class loader (bootstrap class loader)

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

Get an instance

/ / method 1: we can make our code "trusted". When running the program, use the bootclasspath option to specify the system classpath plus a Unsafe path you use, java-Xbootclasspath:/usr/jdk1.7.0/jre/lib/rt.jar:. Com.mishadoff.magic.UnsafeClient// method II static {try {Field field = Unsafe.class.getDeclaredField ("theUnsafe"); field.setAccessible (true); UNSAFE = (Unsafe) field.get (null);} catch (Exception e) {}}

Note: ignore your IDE. For example, eclipse displays "Access restriction..." Error, but if you run the code, it will work properly. If this error message is annoying, you can avoid it by setting the following:

Preferences-> Java-> Compiler-> Errors/Warnings-> Deprecated and restricted API-> Forbidden reference-> Warning

Key API

AllocateInstance (Class var1) does not call the constructor to generate the object

User instance = (User) UNSAFE.allocateInstance (User.class)

ObjectFieldOffset (Field var1) returns the offset of the address of the member property in memory relative to the memory address of the object

PutLong,putInt,putDouble,putChar,putObject and other methods to modify in-memory data directly (access permissions can be overstepped)

Package com.quancheng;import sun.misc.Unsafe;import java.lang.reflect.Field;public class CollectionApp {private static sun.misc.Unsafe UNSAFE; public static void main (String [] args) {try {User instance = (User) UNSAFE.allocateInstance (User.class); instance.setName ("luoyoub"); System.err.println ("instance:" + instance); instance.test () Field name = instance.getClass (). GetDeclaredField ("name"); UNSAFE.putObject (instance, UNSAFE.objectFieldOffset (name), "huanghui"); instance.test ();} catch (Exception e) {e.printStackTrace ();}} static {try {Field field = Unsafe.class.getDeclaredField ("theUnsafe") Field.setAccessible (true); UNSAFE = (Unsafe) field.get (null);} catch (Exception e) {}} class User {private String name; public void setName (String name) {this.name = name;} public void test () {System.err.println ("hello,world" + name);}}

CopyMemory: in-memory data copy

FreeMemory: used to free memory for allocateMemory and reallocateMemory requests

CompareAndSwapInt/compareAndSwapLongCAS operation

GetLongVolatile/putLongVolatile

Use scenarios to avoid initialization

The allocateInstance method is very useful when you want to skip the object initialization phase, bypass the security check of the constructor, or instantiate a class that does not have any common constructor. Initializing it with constructor, reflection, and unsafe will get different results.

Public class CollectionApp {private static sun.misc.Unsafe UNSAFE; public static void main (String [] args) throws IllegalAccessException, InstantiationException {AA = new A (); a.test (); / / output = = > 1A A1 = A.class.newInstance (); a1.test (); / / output = > 1A instance = (A) UNSAFE.allocateInstance (A.class); instance.test () / / output = = > 0} static {try {Field field = Unsafe.class.getDeclaredField ("theUnsafe"); field.setAccessible (true); UNSAFE = (Unsafe) field.get (null);} catch (Exception e) {}} class A {private long a; public A () {a = 1 } public void test () {System.err.println ("aversion = >" + a);}} memory corruption (Memory corruption)

Unsafe can be used to bypass common security techniques and modify memory variables directly; in fact, reflection can achieve the same function. But it's worth noting that we can modify any object, even without references to those objects.

Guard guard = new Guard (); guard.giveAccess (); / / false, no access// bypassUnsafe unsafe = getUnsafe (); Field f = guard.getClass (). GetDeclaredField ("ACCESS_ALLOWED"); unsafe.putInt (guard, unsafe.objectFieldOffset (f), 42); / / memory corruptionguard.giveAccess (); / / true, access granted

Note: we do not have to hold a reference to this object

Shallow copy (Shallow copy)

Dynamic class (Dynamic classes)

We can create a class at run time, for example, from a compiled .class file. Read the contents of the class as a byte array and pass it correctly to the defineClass method; this is useful when you have to create the class dynamically and there are some proxies in the existing code

Private static byte [] getClassContent () throws Exception {File f = new File ("/ home/mishadoff/tmp/A.class"); FileInputStream input = new FileInputStream (f); byte [] content = new byte [(int) f.length ()]; input.read (content); input.close (); return content;} byte [] classContents = getClassContent (); Class c = getUnsafe (). DefineClass (null, classContents, 0, classContents.length) C.getMethod ("a") .invoke (c.newInstance (), null); / / 1 throw an exception (Throw an Exception)

This method throws a checked exception, but your code does not have to catch or rethrow it, just like a run-time exception

GetUnsafe () .throwException (new IOException ()); large array (Big Arrays)

As you know, the maximum size of the Java array is Integer.MAX_VALUE. Using direct memory allocation, the size of the array we created is limited by the heap size; in fact, this is out-of-heap memory (off-heap memory) technology, which is partially available in the java.nio package

Memory allocation in this way is not on the heap and is not managed by GC, so care must be taken with the use of Unsafe.freeMemory (). It also does not perform any boundary checks, so any illegal access may cause JVM to crash

Class SuperArray {private final static int BYTE = 1; private long size; private long address; public SuperArray (long size) {this.size = size; address = getUnsafe (). AllocateMemory (size * BYTE);} public void set (long I, byte value) {getUnsafe (). PutByte (address + I * BYTE, value);} public int get (long idx) {return getUnsafe (). GetByte (address + idx * BYTE) } public long size () {return size;}} long SUPER_SIZE = (long) Integer.MAX_VALUE * 2 SuperArray array = new SuperArray (SUPER_SIZE); System.out.println ("Array size:" + array.size ()); / / 4294967294for (int I = 0; I

< 100; i++) { array.set((long)Integer.MAX_VALUE + i, (byte)3); sum += array.get((long)Integer.MAX_VALUE + i);}System.out.println("Sum of 100 elements:" + sum); // 300并发(Concurrency) 几句关于Unsafe的并发性。compareAndSwap方法是原子的,并且可用来实现高性能的、无锁的数据结构 挂起与恢复 定义: public native void unpark(Thread jthread); public native void park(boolean isAbsolute, long time); // isAbsolute参数是指明时间是绝对的,还是相对的 将一个线程进行挂起是通过park方法实现的,调用park后,线程将一直阻塞直到超时或者中断等条件出现。unpark可以终止一个挂起的线程,使其恢复正常。整个并发框架中对线程的挂起操作被封装在 LockSupport类中,LockSupport类中有各种版本pack方法,但最终都调用了Unsafe.park()方法; unpark函数为线程提供"许可(permit)",线程调用park函数则等待"许可"。这个有点像信号量,但是这个"许可"是不能叠加的,"许可"是一次性的;比如线程B连续调用了三次unpark函数,当线程A调用park函数就使用掉这个"许可",如果线程A再次调用park,则进入等待状态,见下例Example1 Example1:// 针对当前线程已经调用过unpark(多次调用unpark的效果和调用一次unpark的效果一样)public static void main(String[] args) throws InterruptedException { Thread currThread = Thread.currentThread(); UNSAFE.unpark(currThread); UNSAFE.unpark(currThread); UNSAFE.unpark(currThread); UNSAFE.park(false, 0); UNSAFE.park(false, 0); System.out.println("SUCCESS!!!");}// 恢复线程interrupt() && UNSAFE.unpark()运行结果一样public static void main(String[] args) throws InterruptedException { Thread currThread = Thread.currentThread(); new Thread(()->

{try {Thread.sleep (3000); System.err.println ("sub thread end"); / / currThread.interrupt (); UNSAFE.unpark (currThread);} catch (Exception e) {e.printStackTrace ();}}). Start (); UNSAFE.park (false, 0); System.out.println ("success requests!") } / / if the relative time (that is, isAbsolute is false) expires, the effect is the same as that of Thread.sleep. What is the difference to be further studied / / the parameter unit after the relative time is nanosecond UNSAFE.park (false, 300000000l); System.out.println ("success time duration!"); long time = System.currentTimeMillis () + 3000 true / absolute time followed by millisecond UNSAFE.park (true, time) System.out.println ("success with others!")

Note that the unpark function can be called before park. For example, thread B calls the unpark function and issues a "permission" to thread A, then when thread A calls park, it finds that it already has a "permission" and it will continue to run immediately. In fact, the park function sometimes returns for no reason even if it is not "licensed". In fact, in SUN Jdk, object.wait () may be pseudo-awakened.

Note: the unpark method is best not to call unpark on the current thread before calling park

The Unsafe APIsun.misc.Unsafe class contains 105 methods. In fact, there are several sets of important methods for various entity operations, some of which are as follows: Info. Only some low-level memory information addressSizepageSizeObjects. Provides a method for manipulating an object and its fields, allocateInstance # #, to directly get the object instance objectFieldOffsetClasses. Provides methods for manipulating classes and their static fields, staticFieldOffsetdefineClassdefineAnonymousClassensureClassInitializedArrays. Exe. Operand array arrayBaseOffsetarrayIndexScaleSynchronization. The low-level synchronization primitive monitorEntertryMonitorEntermonitorExitcompareAndSwapIntputOrderedIntMemory. AllocateMemorycopyMemoryfreeMemorygetAddressgetIntputInt knowledge points of direct memory access method

Unsafe.park () returns directly when it encounters thread termination (unlike Thread.sleep,Thread.sleep, which throws an exception when it encounters thread.interrupt ())

/ / Thread.sleep throws an exception public static void main (String [] args) throws InterruptedException {Thread thread = new Thread (()-> {try {System.err.println ("sub thread start"); Thread.sleep (10000); System.err.println ("sub thread end");} catch (InterruptedException e) {e.printStackTrace ();}}); thread.start () TimeUnit.SECONDS.sleep (3); thread.interrupt (); System.out.println ("success with others!") } output== > sub thread startSUCCESSThe alternate java.lang.InterruptedException: sleep interrupted at java.lang.Thread.sleep (Native Method) at com.quancheng.ConcurrentTest.lambda$main$0 (ConcurrentTest.java:13) at java.lang.Thread.run (Thread.java:745) Process finished with exit code 0public static void main (String [] args) throws InterruptedException {Thread thread = new Thread (()-> {System.err.println ("sub thread start"); UNSAFE.park (false,0) System.err.println ("sub thread end");}); thread.start (); TimeUnit.SECONDS.sleep (3); UNSAFE.unpark (thread); System.out.println ("success thanks thanks!");} output== > sub thread startsub thread endSUCCESS successful completion process finished with exit code 0

Unpark cannot restore threads in sleep and can only be paired with park because licenses issued by unpark can only be monitored by park

Public static void main (String [] args) throws InterruptedException {Thread thread = new Thread (()-> {try {System.err.println ("sub thread start"); TimeUnit.SECONDS.sleep (10); System.err.println ("sub thread end");} catch (Exception e) {e.printStackTrace ();}}); thread.start () TimeUnit.SECONDS.sleep (3); UNSAFE.unpark (thread); System.out.println ("success stories!");} the flexibility of park and unpark

As mentioned above, unpark functions can be called before park, which is their flexibility.

A thread may be before or after other threads unPark, or call park at the same time, so because of the nature of park, it does not have to worry about the timing of its own park, otherwise, if park must be before unpark, it will bring a lot of trouble to programming!

"think about how to deal with the synchronization of two threads.

In Java5, wait/notify/notifyAll is used to synchronize. There is a pain in the wait/notify mechanism. For example, if thread B uses notify to notify thread A, then thread B needs to make sure that thread An is already waiting on the wait call, otherwise thread A may be waiting forever. It hurts when you program.

In addition, do you want to call notify or notifyAll?

Notify wakes up only one thread, and it would be tragic if two threads were mistakenly wait waiting on the same object. For security reasons, it seems that we can only call notifyAll. "

The park/unpark model really decouples the synchronization between threads. Threads no longer need an Object or other variables to store state, and they no longer need to care about each other's state.

This is the end of the content of "what are the knowledge points of Java Unsafe". Thank you for your reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report