java编程之:Unsafe类

Unsafe类在jdk 源码的多个类中用到,这个类的提供了一些绕开JVM的更底层功能,基于它的实现可以提高效率。但是,它是一把双刃剑:正如它的名字所预示的那样,它是 Unsafe的,它所分配的内存需要手动free(不被GC回收)。Unsafe类,提供了JNI某些功能的简单替代:确保高效性的同时,使事情变得更简 单。

这篇文章主要是以下文章的整理、翻译。

http://mishadoff.com/blog/java-magic-part-4-sun-dot-misc-dot-unsafe/

1. Unsafe API的大部分方法都是native实现,它由105个方法组成,主要包括以下几类:

(1)Info相关。主要返回某些低级别的内存信息:addressSize(), pageSize()

(2)Objects相关。主要提供Object和它的域操纵方法:allocateInstance(),objectFieldOffset()

(3)Class相关。主要提供Class和它的静态域操纵方法:staticFieldOffset(),defineClass(),defineAnonymousClass(),ensureClassInitialized()

(4)Arrays相关。数组操纵方法:arrayBaseOffset(),arrayIndexScale()

(5)Synchronization相关。主要提供低级别同步原语(如基于CPU的CAS(Compare-And-Swap)原 语):monitorEnter(),tryMonitorEnter(),monitorExit(),compareAndSwapInt(),putOrderedInt()

(6)Memory相关。直接内存访问方法(绕过JVM堆直接操纵本地内存):allocateMemory(),copyMemory(),freeMemory(),getAddress(),getInt(),putInt()

 1 package com.yeepay.sxf.hashmaptest;
 2
 3 import java.lang.reflect.Field;
 4
 5 import sun.misc.Unsafe;
 6
 7 public class TestUnSafe {
 8
 9     public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, InstantiationException {
10         //获取属性
11         Field f=Unsafe.class.getDeclaredField("theUnsafe");
12         //
13         f.setAccessible(true);
14         //获取实例
15         Unsafe unsafe=(Unsafe) f.get(null);
16
17         //实例化一个类
18         Player player=(Player) unsafe.allocateInstance(Player.class);
19         //打印年龄   打印结果:0
20         System.out.println("TestUnSafe.enclosing_method()"+player.getAge());
21
22         player.setAge(100);
23
24         //打印结果100
25         System.out.println("TestUnSafe.main()"+player.getAge());
26
27     }
28
29 }
30
31 /**
32  * 普通类
33  * @author sxf
34  *
35  */
36 class Player{
37     //年龄
38     private int age=12;
39
40     //构造函数私有化
41     private Player(){
42         this.age=50;
43     }
44
45     public int getAge() {
46         return age;
47     }
48
49     public void setAge(int age) {
50         this.age = age;
51     }
52 }

View Code

【一】
public native long objectFieldOffset(Field field);
==> 返回指定静态field的内存地址偏移量,在这个类的其他方法中这个值只是被用作一个访问
==>特定field的一个方式。这个值对于 给定的field是唯一的,并且后续对该方法的调用都应该返回相同的值

【二】
public native boolean compareAndSwapInt(Object obj, long offset, int expect, int update);
==>在obj的offset位置比较long field和期望的值,如果相同则更新。这个方法的操作应该是原子的,因此提供了一种不可中断的方式更新long field。成功返回true,不成功返回false
==>obj:包含要修改field的对象
==>offset:obj对象中long型field的偏移量
==>expect:希望field中存在的值
==>update:如果期望值expect与field的当前值相同,设置filed的值为这个新值

【三】
public native boolean compareAndSwapObject(Object obj, long offset, Object expect, Object update);
==>在obj的offset位置比较object field和期望的值,如果相同则更新。这个方法的操作应该是原子的,因此提供了一种不可中断的方式更新object field.成功返回true,不成功返回false
==>obj:包含要修改field的对象
==>offset:obj中object型field的偏移量
==>expect:希望field中存在的值
==>update:如果期望值expect与field的当前值相同,设置filed的值为这个新值

【四】
public native void putOrderedInt(Object obj, long offset, int value);
==>设置obj对象中offset偏移地址对应的整型field的值为指定值。这是一个有序或者有延迟的putIntVolatile方法,并且不保证值的改变被其他线程立即看到。只有在field被<code>volatile</code>修饰并且期望被意外修改的时候使用才有用。
==>obj:  包含要修改field的对象
==>offset:    <code>obj</code>中整型field的偏移量
==>value:   field将被设置的新值

【五】
 public native void putOrderedLong(Object obj, long offset, long value);
==>设置obj对象中offset偏移地址对应的long型field的值为指定值。这是一个有序或者有延迟的<code>putLongVolatile</cdoe>方法,并且不保证值的改变被其他线程立即看到。只有在field被<code>volatile</code>修饰并且期望被意外修改的时候使用才有用。
==>obj:包含需要修改field的对象
==>offset:<code>obj</code>中long型field的偏移量
==>value:field将被设置的新值

【六】
  public native void putOrderedObject(Object obj, long offset, Object value);
==>设置obj对象中offset偏移地址对应的整型field的值为指定值。支持volatile store语义
==>obj:包含需要修改field的对象
==>offset:<code>obj</code>中整型field的偏移量
==>value:field将被设置的新值

【七】
public native void putIntVolatile(Object obj, long offset, int value);
==>设置obj对象中offset偏移地址对应的整型field的值为指定值。支持volatile store语义
==>obj: 包含需要修改field的对象
==>offset:<code>obj</code>中整型field的偏移量
==>value:field将被设置的新值

【八】
 public native int getIntVolatile(Object obj, long offset);
==>获取obj对象中offset偏移地址对应的整型field的值,支持volatile load语义。
==>obj: 包含需要去读取的field的对象
==>offset:<code>obj</code>中整型field的偏移量

【九】
 public native void putLongVolatile(Object obj, long offset, long value);
==>设置obj对象中offset偏移地址对应的long型field的值为指定值。
==>obj:包含需要修改field的对象
==>offset: <code>obj</code>中long型field的偏移量
==>value: field将被设置的新值

【十】
public native long getLongVolatile(Object obj, long offset);
==>获取obj对象中offset偏移地址对应的long型field的值,支持volatile load语义。
==> obj:包含需要去读取的field的对象
==>offset:<code>obj</code>中long型field的偏移量

【十一】
public native void putLong(Object obj, long offset, long value);
==>设置obj对象中offset偏移地址对应的long型field的值为指定值。
==>obj:包含需要修改field的对象
==>offset: <code>obj</code>中long型field的偏移量
==>value:field将被设置的新值

【十二】
public native long getLong(Object obj, long offset);
==> 获取obj对象中offset偏移地址对应的long型field的值
==>obj:包含需要去读取的field的对象
==>offset:<code>obj</code>中long型field的偏移量

【十三】
 public native void putObjectVolatile(Object obj, long offset, Object value);
==> 设置obj对象中offset偏移地址对应的object型field的值为指定值。
==>obj:包含需要修改field的对象
==>offset:<code>obj</code>中object型field的偏移量
==>value:field将被设置的新值

【十四】
public native Object getObjectVolatile(Object obj, long offset);
==>获取obj对象中offset偏移地址对应的object型field的值,支持volatile load语义。
==>obj:包含需要去读取的field的对象
==>offset:  <code>obj</code>中object型field的偏移量

【十五】
  public native int arrayBaseOffset(Class arrayClass);
==>获取给定数组中第一个元素的偏移地址。 为了存取数组中的元素,这个偏移地址与<a href="#arrayIndexScale"><code>arrayIndexScale* </code></a>方法的非0返回值一起被使用
==>arrayClass:第一个元素地址被获取的class
==>返回:数组第一个元素 的偏移地址

【十六】
 public native int arrayIndexScale(Class arrayClass);
==>获取用户给定数组寻址的换算因子.一个合适的换算因子不能返回的时候(例如:基本类型), 返回0.这个返回值能够与<a href="#arrayBaseOffset"><code>arrayBaseOffset</code> </a>一起使用去存取这个数组class中的元素

【十七】
public native void unpark(Thread thread);
==>释放被<a href="#park"><code>park</code></a>创建的在一个线程上的阻塞.这个方法也可以被使用来终止一个先前调用<code>park</code>导致的阻塞.这个操作操作时不安全的,因此线程必须保证是活的.这是java代码不是native代码
==>thread:  要解除阻塞的线程

【十八】
public native void park(boolean isAbsolute, long time);
==>阻塞一个线程直到<a href="#unpark"><code>unpark</code></a>出现、线程被中断或者timeout时间到期。如果一个<code>unpark</code>调用已经出现了,这里只计数。timeout为0表示永不过期.当<code>isAbsolute</code>为true时,timeout是相对于新纪元之后的毫秒。否则这个值就是超时前的纳秒数。这个方法执行时也可能不合理地返回(没有具体原因)
==>isAbsolute:如果为true timeout的值是一个相对于新纪元之后的毫秒数
==>time:  可以是一个要等待的纳秒数,或者是一个相对于新纪元之后的毫秒数直到到达这个时间点

时间: 2024-10-26 01:28:10

java编程之:Unsafe类的相关文章

实例讲解Java并发编程之ThreadLocal类_java

ThreadLocal类可以理解为ThreadLocalVariable(线程局部变量),提供了get与set等访问接口或方法,这些方法为每个使用该变量的线程都存有一份独立的副本,因此get总是返回当前执行线程在调用set时设置的最新值.可以将ThreadLocal<T>视为 包含了Map<Thread,T>对象,保存了特定于该线程的值. 概括起来说,对于多线程资源共享的问题,同步机制采用了"以时间换空间"的方式,而ThreadLocal采用了"以空间

Java编程之Map中分拣思想。

题目:给定一个字符串,求出字符串中每一个单词在字符串中出现的次数 旨意:map的分拣思想.   每一个key的包装类,存放出现的次数 1 /** 2 * 作为包装类,用来存放英文单词,和该英文单词出现的次数 3 * @ClassName: Str 4 * @Description: TODO(这里用一句话描述这个类的作用) 5 * @author 尚晓飞 6 * @date 2014-7-30 下午6:57:29 7 * 8 */ 9 public class Str { 10 private

Java编程之Date的相关操作

一:讲字符串的时间格式数据转换成时间对象 1 //将字符串的时间数据,转换成时间 2 String dateString="2007-12-12"; 3 DateFormat date=new SimpleDateFormat("yyyy-MM-dd"); 4 Date dat=date.parse(dateString); View Code  二:通过System类获取系统当前时间,数字表现形式.和将其转换成时间类Date的实例.时间格式的控制. 1 //获取当

java编程之:生成rsa密钥

通过openssl工具生成RSA的公钥和私钥(opnssl工具可在互联网中下载到,也可以点此下载无线接口包,里面包含此工具) 打开openssl文件夹下的bin文件夹,执行openssl.exe文件:1)生成RSA私钥 输入"生成命令.txt"文件中:"genrsa -out rsa_private_key.pem 1024",并回车得到生成成功的结果,如下图: 此时,我们可以在 bin文件夹中看到一个文件名为rsa_private_key.pem的文件,用记事本方

java编程之:按位与运算,等运算规则

  按位与运算符(&) 参加运算的两个数据,按二进制位进行"与"运算. 运算规则:0&0=0;   0&1=0;    1&0=0;     1&1=1;        即:两位同时为"1",结果才为"1",否则为0 例如:3&5  即 0000 0011 & 0000 0101 = 0000 0001   因此,3&5的值得1.   另,负数按补码形式参加按位与运算. "

java编程之:org.apache.commons.lang3.text.StrTokenizer

第一个api测试:按特殊符号进行分词,并遍历每一个分词部分 1 public static void main(String[] args) { 2 String aString="AB-CD-EF-GH-IJ-KL-MN-OP-QR-ST-UV-WX-YZ"; 3 StrTokenizer strTokenizer=new StrTokenizer(aString, "-"); 4 while(true){ 5 System.out.println("P

sun.misc.unsafe类的用法

这个帖子是关于JAVA中鲜为人知的特性的后续更新,如果想得到下次在线讨论的更新,请通过邮件订阅,并且不要忘了在评论区留下你的意见和建议. Java是一个安全的开发工具,它阻止开发人员犯很多低级的错误,而大部份的错误都是基于内存管理方面的.如果你想搞破坏,可以使用Unsafe这个类.这个类是属于sun.* API中的类,并且它不是J2SE中真正的一部份,因此你可能找不到任何的官方文档,更可悲的是,它也没有比较好的代码文档. 实例化sun.misc.Unsafe 如果你尝试创建Unsafe类的实例,

Android编程之ICS式下拉菜单PopupWindow实现方法详解(附源码下载)_Android

本文实例讲述了Android编程之ICS式下拉菜单PopupWindow实现方法.分享给大家供大家参考,具体如下: 运行效果截图如下: 右边这个就是下拉菜单啦,看见有的地方叫他 ICS式下拉菜单,哎哟,不错哦! 下面先讲一下实现原理: 这种菜单实际上就是一个弹出式的菜单,于是我们想到android PopupWindow 类,给他设置一个view 在弹出来不就OK了吗. PopupWindow 的用法也很简单 主要方法: 步骤1.new 一个实例出来,我们使用这个构造方法即可, 复制代码 代码如

Android编程之在SD卡上进行文件读写操作实例详解_Android

本文实例讲述了Android编程之在SD卡上进行文件读写操作的方法.分享给大家供大家参考,具体如下: 很多知识只有真正理解掌握之后才能运用自如,举一反三.对Java中的文件操作和android系统SD卡里面的文件操作,你觉得有区别吗,显然没有本质区别,如果勉强说有,那也是不足为道滴,但我们在实际运用中却要注意如下几点,不然问题会缠上你. 1.首先想要对android系统SD卡里文件操作需要添加使用权限: android系统是不会让外来程序随意动自己内存的,如果没有许可证,不好意思,不准你动我地盘