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()

 package com.yeepay.sxf.hashmaptest;

 import java.lang.reflect.Field;

 import sun.misc.Unsafe;

 public class TestUnSafe {

     public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, InstantiationException {
//获取属性
Field f=Unsafe.class.getDeclaredField("theUnsafe");
//
f.setAccessible(true);
//获取实例
Unsafe unsafe=(Unsafe) f.get(null); //实例化一个类
Player player=(Player) unsafe.allocateInstance(Player.class);
//打印年龄 打印结果:0
System.out.println("TestUnSafe.enclosing_method()"+player.getAge()); player.setAge(100); //打印结果100
System.out.println("TestUnSafe.main()"+player.getAge()); } } /**
* 普通类
* @author sxf
*
*/
class Player{
//年龄
private int age=12; //构造函数私有化
private Player(){
this.age=50;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
}
}

【一】
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:  可以是一个要等待的纳秒数,或者是一个相对于新纪元之后的毫秒数直到到达这个时间点

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

  1. [深入浅出WP8.1(Runtime)]网络编程之HttpClient类

    12.2 网络编程之HttpClient类 除了可以使用HttpWebRequest类来实现HTTP网络请求之外,我们还可以使用HttpClient类来实现.对于基本的请求操作,HttpClient类 ...

  2. Java中的Unsafe类111

    1.Unsafe类介绍 Unsafe类是在sun.misc包下,不属于Java标准.但是很多Java的基础类库,包括一些被广泛使用的高性能开发库都是基于Unsafe类开发的,比如Netty.Hadoo ...

  3. 网络编程之HttpClient类(转)

    12.2 网络编程之HttpClient类 除了可以使用HttpWebRequest类来实现HTTP网络请求之外,我们还可以使用HttpClient类来实现.对于基本的请求操作,HttpClient类 ...

  4. Java安全之Unsafe类

    Java安全之Unsafe类 0x00 前言 前面使用到的一些JNI编程和Javaagent等技术,其实在安全里面的运用非常的有趣和微妙,这个已经说过很多次.后面还会发现一些比较有意思的技术,比如AS ...

  5. Java sun.misc.Unsafe类的学习笔记

    Java未开源的Unsafe类 Unsafe类可以为我们提供高效并且线程安全方式操作变量,直接和内存数据打交道. 获取Unsafe实体的方法 private static Unsafe getUnsa ...

  6. Java sun.misc.unsafe类

    Java是一个安全的开发工具,它阻止开发人员犯很多低级的错误,而大部份的错误都是基于内存管理方面的.如果你想搞破坏,可以使用Unsafe这个类.这个类是属于sun.*API中的类,并且它不是J2SE中 ...

  7. Java双刃剑之Unsafe类详解

    前一段时间在研究juc源码的时候,发现在很多工具类中都调用了一个Unsafe类中的方法,出于好奇就想要研究一下这个类到底有什么作用,于是先查阅了一些资料,一查不要紧,很多资料中对Unsafe的态度都是 ...

  8. Java并发编程之ThreadLocal类

    ThreadLocal类可以理解为ThreadLocalVariable(线程局部变量),提供了get与set等访问接口或方法,这些方法为每个使用该变量的线程都存有一份独立的副本,因此get总是返回当 ...

  9. 并发编程之 Thread 类过期方法和常用方法

    前言 在 Java 刚诞生时,Thread 类就已经有了很多方法,但这些方法由于一些原因(有一些明显的bug或者设计不合理)有些已经废弃了,但是他们的方法名却是非常的好,真的是浪费.我们在进行并发必编 ...

随机推荐

  1. 利用ps指令查看某个程序的进程状态

    ps -ef是查看所有的进程,然后用grep筛选出你要的信息. eg.

  2. jquery的is用法

    JQuery 中 is(':visible') 解析及用法 javascript代码$(document).ready(function() {           $('#faq').find('d ...

  3. Thread启动方式一(Thread.start):源码分析

    package day11; class TestDemo extends Thread{ int count = 0; /*public void add(){ while(count<100 ...

  4. Airbase-ng帮助

    Airbase-ng 1.2 rc2 - (C) 2008-2014 Thomas d'Otreppe  Original work: Martin Beck  http://www.aircrack ...

  5. hdu 2099

    PS:因为还是不爽...继续水题...感觉这道题就是考输出.. 代码: #include "stdio.h" void cal(int a,int b); int main(){ ...

  6. mahout中kmeans算法和Canopy算法实现原理

    本文讲一下mahout中kmeans算法和Canopy算法实现原理. 一. Kmeans是一个很经典的聚类算法,我想大家都非常熟悉.虽然算法较为简单,在实际应用中却可以有不错的效果:其算法原理也决定了 ...

  7. pyplot基本绘制(二)

    本节主要解决在一个figure中放置多福图,以及图中一些注释文字的添加等问题. 先看一个效果图: 下面是实现代码: __author__ = 'hust' import numpy as np imp ...

  8. js 检测 flash插件以及版本号 通用所有浏览器

    var fls = flashChecker(); if (fls.h) { if (fls.v < parseFloat('8.0')) { alert("您当前的flash pla ...

  9. 为什么有的代码要用 base64 进行编码

    一.1.传输信道只支持ASCII字符,不方便传输二进制流的场合. 2.含有非ASCII字符,容易出现编码问题的场合. 3.简易的掩人耳目.至少非开发人一眼看不出来是啥. 二.Base64主要用于将不可 ...

  10. Ext.Net系列:一安装与使用

    http://www.cnblogs.com/howDo/archive/2011/04/27/2031084.html 下载地址:http://www.ext.net/download/ 示例地址: ...