JDK中Unsafe类详解
http://hg.openjdk.java.net/jdk7/jdk7/jdk/file/9b8c96f96a0f/src/share/classes/sun/misc/Unsafe.java
http://hg.openjdk.java.net/jdk7/jdk7/hotspot/file/tip/src/share/vm/prims/unsafe.cpp
http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/sun/misc/Unsafe.java
http://hg.openjdk.java.net/jdk8/jdk8/hotspot/file/tip/src/share/vm/prims/unsafe.cpp
案例代码
package com.dsp.unsafe; import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.concurrent.locks.ReentrantLock; import com.alibaba.fastjson.JSON;
import com.dsp.json.Person; import sun.misc.Unsafe; @SuppressWarnings("restriction")
public class UnsafeDemo { static class Test {
private final int x; Test(int x) {
this.x = x;
System.out.println("Test ctor");
} int getX() {
return x;
} } public static void main(String[] args) throws InstantiationException, NoSuchFieldException {
// 获得一个UnSafe实例
Unsafe unsafe = null;
try {
Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
unsafe = (Unsafe) f.get(null);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} if (unsafe != null) {
try {
// 构造一个对象,且不调用其构造函数
Test test = (Test) unsafe.allocateInstance(Test.class);
// 得到一个对象内部属性的地址
long x_addr = unsafe.objectFieldOffset(Test.class.getDeclaredField("x"));
// 直接给此属性赋值
unsafe.getAndSetInt(test, x_addr, 47);
System.out.println(test.getX());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
} // 通过地址操作数组
if (unsafe != null) {
final int INT_BYTES = 4;
int[] data = new int[10];
System.out.println(Arrays.toString(data)); long arrayBaseOffset = unsafe.arrayBaseOffset(int[].class);
System.out.println("Array address is :" + arrayBaseOffset);
long arrayBaseOffset2 = unsafe.arrayBaseOffset(double[].class);
System.out.println("Array address is :" + arrayBaseOffset2); unsafe.putInt(data, arrayBaseOffset, 47);
unsafe.putInt(data, arrayBaseOffset + INT_BYTES * 8, 43);
System.out.println(Arrays.toString(data));
} // CAS
if (unsafe != null) {
Test test = (Test) unsafe.allocateInstance(Test.class);
long x_addr = unsafe.objectFieldOffset(Test.class.getDeclaredField("x"));
unsafe.getAndSetInt(test, x_addr, 47);
unsafe.compareAndSwapInt(test, x_addr, 47, 78);
System.out.println("After CAS:" + test.getX());
} } @SuppressWarnings("deprecation")
public static void mainB(String[] args)
throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
Unsafe UNSAFE = (Unsafe) theUnsafe.get(null);
System.out.println(UNSAFE); byte[] data = new byte[10];
System.out.println(Arrays.toString(data)); int byteArrayBaseOffset = UNSAFE.arrayBaseOffset(byte[].class);
System.out.println(byteArrayBaseOffset); UNSAFE.putByte(data, byteArrayBaseOffset, (byte) 1);
UNSAFE.putByte(data, byteArrayBaseOffset + 5, (byte) 5);
System.out.println(Arrays.toString(data)); UNSAFE.setMemory(data, byteArrayBaseOffset, 1, (byte) 2);
UNSAFE.setMemory(data, byteArrayBaseOffset + 5, 1, (byte) 6);
System.out.println(Arrays.toString(data));
} @SuppressWarnings({ "unused", "rawtypes" })
public static void mainA(String[] args)
throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
Unsafe unsafe = (Unsafe) field.get(null); long allocateMemory = unsafe.allocateMemory(1024);
long theUnsafeOffset = unsafe.staticFieldOffset(field);
System.out.println(theUnsafeOffset); /********************************************************************************
* 获取对象中某字段在内存中的偏移量
*/
// 开始使用unsafe对象,分别找到Person对象中name属性和age属性的内存地址偏移量
// 首先是Person类中的name属性,在内存中设定的偏移位置
Field field2 = Person.class.getDeclaredField("name");
// 一旦这个类实例化后,该属性在内存中的偏移位置
long offset2 = unsafe.objectFieldOffset(field2);
System.out.println("name offset = " + offset2);
/*
* 然后是Person类中的age属性,在内存中设定的偏移位置
*/
Field age3 = Person.class.getDeclaredField("age");
long ageOffset3 = unsafe.objectFieldOffset(age3);
System.out.println("age offset = " + ageOffset3); /********************************************************************************
* 修改某个字段的数据
*/
/*
* 修改字段数据
*/
Person person = new Person();
person.setName("dsp");
person.setAge(20);
/*
* 获取age属性的内存地址偏移量
*/
Field ageField = Person.class.getDeclaredField("age");
long ageOffset = unsafe.objectFieldOffset(ageField);
/*
* 比较并修改值 1、需要修改的对象 2、更改属性的内存偏移量 3、预期的值 4、设置的新值
*/
if (unsafe.compareAndSwapInt(person, ageOffset, 20, 26)) {
System.out.println("修改数据成功");
} else {
System.out.println("修改数据失败");
}
System.out.println(JSON.toJSONString(person)); int ss, ts;
try {
Class<Segment[]> sc = Segment[].class;
SBASE = unsafe.arrayBaseOffset(sc);
ss = unsafe.arrayIndexScale(sc);
} catch (Exception e) {
throw new Error(e);
}
SSHIFT = 31 - Integer.numberOfLeadingZeros(ss); System.out.println("SBASE=" + SBASE);
System.out.println("ss=" + ss);
System.out.println("SSHIFT=" + SSHIFT); int ARRAY_INT_BASE_OFFSET = unsafe.arrayBaseOffset(int[].class);
int ARRAY_INT_INDEX_SCALE = unsafe.arrayIndexScale(int[].class);
System.out.println("ARRAY_INT_BASE_OFFSET=" + ARRAY_INT_BASE_OFFSET);
System.out.println("ARRAY_INT_INDEX_SCALE=" + ARRAY_INT_INDEX_SCALE);
} // Unsafe mechanics
private static long SBASE;
private static long SSHIFT; static final class Segment<K, V> extends ReentrantLock implements Serializable {
/*
* Segments maintain a table of entry lists that are always kept in a consistent
* state, so can be read (via volatile reads of segments and tables) without
* locking. This requires replicating nodes when necessary during table
* resizing, so the old lists can be traversed by readers still using old
* version of table.
*
* This class defines only mutative methods requiring locking. Except as noted,
* the methods of this class perform the per-segment versions of
* ConcurrentHashMap methods. (Other methods are integrated directly into
* ConcurrentHashMap methods.) These mutative methods use a form of controlled
* spinning on contention via methods scanAndLock and scanAndLockForPut. These
* intersperse tryLocks with traversals to locate nodes. The main benefit is to
* absorb cache misses (which are very common for hash tables) while obtaining
* locks so that traversal is faster once acquired. We do not actually use the
* found nodes since they must be re-acquired under lock anyway to ensure
* sequential consistency of updates (and in any case may be undetectably
* stale), but they will normally be much faster to re-locate. Also,
* scanAndLockForPut speculatively creates a fresh node to use in put if no node
* is found.
*/
private static final long serialVersionUID = 2249069246763182397L; /**
* The maximum number of times to tryLock in a prescan before possibly blocking
* on acquire in preparation for a locked segment operation. On multiprocessors,
* using a bounded number of retries maintains cache acquired while locating
* nodes.
*/
static final int MAX_SCAN_RETRIES = Runtime.getRuntime().availableProcessors() > 1 ? 64 : 1;
} }
:)
JDK中Unsafe类详解的更多相关文章
- Java中Unsafe类详解
http://www.cnblogs.com/mickole/articles/3757278.html Java不能直接访问操作系统底层,而是通过本地方法来访问.Unsafe类提供了硬件级别的原子操 ...
- 【Java深入研究】8、Java中Unsafe类详解
java不能直接访问操作系统底层,而是通过本地方法来访问.Unsafe类提供了硬件级别的原子操作,主要提供了以下功能: 1.通过Unsafe类可以分配内存,可以释放内存: 类中提供的3个本地方法all ...
- Java中dimension类详解
Java中dimension类详解 https://blog.csdn.net/hrw1234567890/article/details/81217788
- Java双刃剑之Unsafe类详解
前一段时间在研究juc源码的时候,发现在很多工具类中都调用了一个Unsafe类中的方法,出于好奇就想要研究一下这个类到底有什么作用,于是先查阅了一些资料,一查不要紧,很多资料中对Unsafe的态度都是 ...
- 4、Python中的类详解(0601)
<大话数据结构>的作者程杰在博客园也有博客,网址是:http://cj723.cnblogs.com/ 面向对象编程(OOP) 1.程序 = 指令 + 数据 代码可以选择以指令为核心或以数 ...
- Java中Class类详解、用法及泛化
Java中Class类及用法 Java程序在运行时,Java运行时系统一直对所有的对象进行所谓的运行时类型标识,即所谓的RTTI.这项信息纪录了每个对象所属的类.虚拟机通常使用运行时类型信息选准正确方 ...
- Java中ArrayList类详解
1.什么是ArrayList ArrayList就是传说中的动态数组,用MSDN中的说法,就是Array的复杂版本,它提供了如下一些好处: 动态的增加和减少元素 实现了ICollection和ILis ...
- 【转】C#中PrintDocument类详解
PrintDocument组件是用于完成打印的类,其常用属性.方法和事件如下: 属性DocumentName:字符串类型,记录打印文档时显示的文档名(例如,在打印状态对话框或打印机队列中显示). 方法 ...
- python中deque类详解
最近在pythonTip做题的时候,遇到了deque类,以前对其不太了解,现在特此总结一下 deque类是python标准库collections模块中的一项,它提供了两端都可以操作的序列,这意味着, ...
随机推荐
- webView加载url,加载指定字符串
//加载url-(void)addWebView{ UIWebView * webView = [[UIWebView alloc] initWithFrame:CGRectMake(, , zScr ...
- Windows10关机问题----只有“睡眠”、“更新并重启”、“更新并关机”,但是又不想更新,解决办法
最近的一个问题,电脑关机的时候发现,只有“睡眠”.“更新并重启”.“更新并关机” 内心很是煎熬.... 尝试了N种方式,然后总结如下: 第一种方式:(表示自己window的系统用着挺好,力荐) 1.打 ...
- Python的JAVA胶水——jpype
Python的JAVA胶水--jpype python可以作为一门胶水语言使用,可以用其它语言的优势来弥补自身如性能方面的不足,jpype就是在Python中使用jvm的第三方库 文档在这里 安装 s ...
- KeepAlived+MySQL互为主从
http://blog.csdn.net/socho/article/details/51804720 解决Master单点问题,两台mysql互为主备,双向replication.当一master挂 ...
- selenium 3+java 配置全
之前有配置过java+selenium的环境,感觉将的不够详细,这里重新写一篇,以便日后复习,和大家共享. 一.准备工作. 首先在配置之前需要准备以下: JDK Eclipse Sel ...
- django之模型层(model)--添加、单表查询、修改基础
上篇带大家简单做了一下图书表的创建.简单的查看和删除,今天会先简单介绍添加和修改,因为添加和修改与删除一样都很简单,本篇会相对多介绍一点单表查询,大家都知道数据库中查询是最重要的一部分,毕竟无论是修改 ...
- ASP.NET微信公众号获取AccessToken
access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token.开发者需要进行妥善保存.access_token的存储至少要保留512个字符空间.acces ...
- Java的内存管理机制之内存区域划分
各位,好久不见.先做个预告,由于最近主要在做Java服务端开发,最近一段时间会更新Java服务端开发相关的一些知识,包括但不限于一些读书笔记.框架的学习笔记.和最近一段时间的思考和沉淀.先从Java虚 ...
- 什么是ip代理
1.什么是代理IP(代理服务器),代理IP(代理服务器)有什么用? 代理服务器英文全称是(Proxy Server),也叫做代理IP,其功能就是代理网络用户去取得网络信息.形象的说:它是网络信息的中转 ...
- 汉诺塔系列问题: 汉诺塔II、汉诺塔III、汉诺塔IV、汉诺塔V、汉诺塔VI
汉诺塔 汉诺塔II hdu1207: 先说汉若塔I(经典汉若塔问题),有三塔.A塔从小到大从上至下放有N个盘子.如今要搬到目标C上. 规则小的必需放在大的上面,每次搬一个.求最小步数. 这个问题简单, ...