您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > JAVA

Java中Unsafe使用详解

时间:2021-03-30 14:13:36  来源:今日头条  作者:FastCoder

环境:JAVA8


Unsafe介绍

Unsafe是位于sun.misc包下的一个类,主要提供一些用于执行低级别、不安全操作的方法,如直接访问系统内存资源、自主管理内存资源等,这些方法在提升Java运行效率、增强Java语言底层资源操作能力方面起到了很大的作用。但由于Unsafe类使得Java语言拥有了类似C语言指针一样操作内存空间的能力,这无疑也增加了程序发生相关指针问题的风险。在程序中过度、不正确使用Unsafe类会使得程序出错的概率变大,使得Java这种安全的语言变得不再“安全”,因此对Unsafe的使用一定要慎重。
java.util.concurrent.atomic包下的原子操作类,基本都是使用Unsafe实现的。

Unsafe提供的API大致可分为内存操作、CAS、Class、对象操作、线程、系统信息获取、内存屏障、数组操作等几类。

内存相关

Java中Unsafe使用详解

 

CAS相关

Java中Unsafe使用详解

 


java.util.concurrent.atomic包中的原子类基本都用的Unsafe

private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;
static {
  try {
    valueOffset = unsafe.objectFieldOffset(AtomicInteger.class.getDeclaredField("value"));
  } catch (Exception ex) { throw new Error(ex); }
}
public final int getAndSet(int newValue) {
  return unsafe.getAndSetInt(this, valueOffset, newValue);
}

线程相关

Java中Unsafe使用详解

 

LockSupport类中有应用unpark,park

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

Class相关

Java中Unsafe使用详解

 

对象操作相关

Java中Unsafe使用详解

 


Java中Unsafe使用详解

 

系统相关

Java中Unsafe使用详解

 

内存屏障

Java中Unsafe使用详解

 

loadFence:保证在这个屏障之前的所有读操作都已经完成。
storeFence:保证在这个屏障之前的所有写操作都已经完成。
fullFence:保证在这个屏障之前的所有读写操作都已经完成。

在java8中 有这个StampedLock类,该类中应用了内存屏障功能。

private static final sun.misc.Unsafe U;
static {
  try {
    U = sun.misc.Unsafe.getUnsafe();
  } catch (Exception e) {
    throw new Error(e);
  }
}
public boolean validate(long stamp) {
  U.loadFence();
  return (stamp & SBITS) == (state & SBITS);
}

U.loadFence();

 

Unsafe.java

public final class Unsafe {

    private static native void registerNatives();
    static {
        registerNatives();
        sun.reflect.Reflection.registerMethodsToFilter(Unsafe.class, "getUnsafe");
    }

    private Unsafe() {}

    private static final Unsafe theUnsafe = new Unsafe();
    // ...
}

获取Unsafe实例

Unsafe类是final且是单例的,并且theUnsafe字段是private;通过如下方法获取实例

  • 方法1
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe") ;
theUnsafe.setAccessible(true) ;
Unsafe unsafe = (Unsafe) theUnsafe.get(null) ;
  • 方法2
private static Unsafe unsafe = null ;
	
static {
	try {
		Constructor<Unsafe> cons = Unsafe.class.getDeclaredConstructor() ;
		cons.setAccessible(true) ;
		unsafe = cons.newInstance() ;
	} catch (Exception e) {
		e.printStackTrace();
	}
}

Unsafe简单应用

int i = 0 ;
	
public static void main(String[] args) throws Exception {
	UnsafeDemo d = new UnsafeDemo() ;
	// 获取Unsafe实例
	Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe") ;
	theUnsafe.setAccessible(true) ;
	Unsafe unsafe = (Unsafe) theUnsafe.get(null) ;
	// 获取类的实例变量
	Field f = UnsafeDemo.class.getDeclaredField("i") ;
	// 获取字段相对Java对象的"起始地址"的偏移量
	long fieldOffset = unsafe.objectFieldOffset(f) ;
	System.out.println(fieldOffset) ;
	// 设置值
	boolean success = unsafe.compareAndSwapInt(d, fieldOffset, 0, 10) ;
	System.out.println(success) ;
	System.out.println(d.i) ;
}

Unsafe对象操作

private static Unsafe unsafe = null ;
	
static {
try {
		Constructor<Unsafe> cons = Unsafe.class.getDeclaredConstructor() ;
		cons.setAccessible(true) ;
		unsafe = cons.newInstance() ;
	} catch (Exception e) {
		e.printStackTrace();
	}
}
public static void allocate() {
	try {
		Person p = (Person)unsafe.allocateInstance(Person.class) ;
		p.setId("s001");
		System.out.println(p.getValue()) ;
		System.out.println(p.getId()) ;
	} catch (Exception e) {
		e.printStackTrace();
	}
}

执行结果:

Java中Unsafe使用详解

 

对象操作2:

private Person p = new Person("1", "张三") ;
	
public static void main(String[] args) throws Exception {
  UnSafeObjectDemo d = new UnSafeObjectDemo() ;
  Field field = Unsafe.class.getDeclaredField("theUnsafe") ;
	field.setAccessible(true) ;
	Unsafe unsafe = (Unsafe) field.get(null) ;
	Field f = d.getClass().getDeclaredField("p") ;
	long offset = unsafe.objectFieldOffset(f) ;
	System.out.println(offset) ;
	boolean res = unsafe.compareAndSwapObject(d, offset, d.p, new Person("2", "李四")) ;
	System.out.println(res) ;
	System.out.println(d.p.getName()) ;
}
Java中Unsafe使用详解

 

Unsafe创建对象

当不知道即将使用的对象有何构造函数,或是不想使用现有对象的构造函数创建对象时,可以通过如下方式:

Constructor<Teacher> cons = (Constructor<Teacher>) ReflectionFactory.getReflectionFactory().newConstructorForSerialization(Teacher.class,
				Object.class.getConstructor());
cons.setAccessible(true);
Teacher t = cons.newInstance() ;
System.out.println(t) ;

Unsafe简单实现原子操作类

public class AtomicCount {
	
	private static Unsafe unsafe ;
	
	private int value ;
	private static long valueOffset ;
	
	static {
		try {
			Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe") ;
			theUnsafe.setAccessible(true) ;
			unsafe = (Unsafe) theUnsafe.get(null) ;
			
			Field f = AtomicCount.class.getDeclaredField("value") ;
			valueOffset = unsafe.objectFieldOffset(f) ;
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public AtomicCount(int value) {
		this.value = value ;
	}
	
	public final int get() {
        return value;
    }
	
	public final int getAndIncrement() {
        return unsafe.getAndAddInt(this, valueOffset, 1);
    }
	
}

完毕!!!



Tags:Unsafe   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
环境:java8Unsafe介绍Unsafe是位于sun.misc包下的一个类,主要提供一些用于执行低级别、不安全操作的方法,如直接访问系统内存资源、自主管理内存资源等,这些方法在提升Java运行...【详细内容】
2021-03-30  Tags: Unsafe  点击:(333)  评论:(0)  加入收藏
▌简易百科推荐
一、Redis使用过程中一些小的注意点1、不要把Redis当成数据库来使用二、Arrays.asList常见失误需求:把数组转成list集合去处理。方法:Arrays.asList 或者 Java8的stream流式处...【详细内容】
2021-12-27  CF07    Tags:Java   点击:(3)  评论:(0)  加入收藏
文章目录 如何理解面向对象编程? JDK 和 JRE 有什么区别? 如何理解Java中封装,继承、多态特性? 如何理解Java中的字节码对象? 你是如何理解Java中的泛型的? 说说泛型应用...【详细内容】
2021-12-24  Java架构师之路    Tags:JAVA   点击:(5)  评论:(0)  加入收藏
大家好!我是老码农,一个喜欢技术、爱分享的同学,从今天开始和大家持续分享JVM调优方面的经验。JVM调优是个大话题,涉及的知识点很庞大 Java内存模型 垃圾回收机制 各种工具使用 ...【详细内容】
2021-12-23  小码匠和老码农    Tags:JVM调优   点击:(11)  评论:(0)  加入收藏
前言JDBC访问Postgresql的jsonb类型字段当然可以使用Postgresql jdbc驱动中提供的PGobject,但是这样在需要兼容多种数据库的系统开发中显得不那么通用,需要特殊处理。本文介绍...【详细内容】
2021-12-23  dingle    Tags:JDBC   点击:(12)  评论:(0)  加入收藏
Java与Lua相互调用案例比较少,因此项目使用需要做详细的性能测试,本内容只做粗略测试。目前已完成初版Lua-Java调用框架开发,后期有时间准备把框架进行抽象,并开源出来,感兴趣的...【详细内容】
2021-12-23  JAVA小白    Tags:Java   点击:(10)  评论:(0)  加入收藏
Java从版本5开始,在 java.util.concurrent.locks包内给我们提供了除了synchronized关键字以外的几个新的锁功能的实现,ReentrantLock就是其中的一个。但是这并不意味着我们可...【详细内容】
2021-12-17  小西学JAVA    Tags:JAVA并发   点击:(10)  评论:(0)  加入收藏
一、概述final是Java关键字中最常见之一,表示“最终的,不可更改”之意,在Java中也正是这个意思。有final修饰的内容,就会变得与众不同,它们会变成终极存在,其内容成为固定的存在。...【详细内容】
2021-12-15  唯一浩哥    Tags:Java基础   点击:(14)  评论:(0)  加入收藏
1、问题描述关于java中的日志管理logback,去年写过关于logback介绍的文章,这次项目中又优化了下,记录下,希望能帮到需要的朋友。2、解决方案这次其实是碰到了一个问题,一般的情况...【详细内容】
2021-12-15  软件老王    Tags:logback   点击:(17)  评论:(0)  加入收藏
本篇文章我们以AtomicInteger为例子,主要讲解下CAS(Compare And Swap)功能是如何在AtomicInteger中使用的,以及提供CAS功能的Unsafe对象。我们先从一个例子开始吧。假设现在我们...【详细内容】
2021-12-14  小西学JAVA    Tags:JAVA   点击:(21)  评论:(0)  加入收藏
一、概述观察者模式,又可以称之为发布-订阅模式,观察者,顾名思义,就是一个监听者,类似监听器的存在,一旦被观察/监听的目标发生的情况,就会被监听者发现,这么想来目标发生情况到观察...【详细内容】
2021-12-13  唯一浩哥    Tags:Java   点击:(16)  评论:(0)  加入收藏
相关文章
    无相关信息
最新更新
栏目热门
栏目头条