相信看过java源代码的同学。对 sum.msic.Unsafe 这个类并不陌生,特别是在java.util.concurrent包有非常多的使用。

sum.msic.Unsafe源代码:      http://www.docjar.com/html/api/sun/misc/Unsafe.java.html

javadoc:      http://www.docjar.com/docs/api/sun/misc/Unsafe.html

sum.msic.Unsafe是一个运行低级别(硬件级别的原子操作),不安全操作的方法结合,由于java无法訪问到系统底层,所以我们能够看到sum.msic.Unsafe类大部分都是native的本地方法。尽管该类的方法都是pulblic的,可是我们无法在编程中调用Unsafe(在JDK中能够随意调用),该类仅仅能在授信的代码中使用它的实例。

先介绍下CAS(Compare And Swap)。按字面的理解就是比較并交换。

CAS包括三个操作值:内存地址,新值,预期原值。假设内存地址中的值和预期原值一样,那么则会替换成新值,否则。将不做不论什么操作。在sum.msic.Unsafe
类中有大量的compareAndSwap***方法。比如:compareAndSwapInt,compareAndSwapLong,compareAndSwapObject等等。

AtomicBoolean类,Unsafe对象初始化:
// setup to use Unsafe.compareAndSwapInt for updates
private static final Unsafe unsafe = Unsafe.getUnsafe();

获取Unsafe实例静态方法:

public static Unsafe getUnsafe() {
Class cc = sun.reflect.Reflection.getCallerClass(2);
if (cc.getClassLoader() != null)
throw new SecurityException("Unsafe");
return theUnsafe;
}

接下来简介一下sum.msic.Unsafe的一些方法:

//扩充内存
public native long reallocateMemory(long address, long bytes); //分配内存
public native long allocateMemory(long bytes); //释放内存
public native void freeMemory(long address); //在给定的内存块中设置值
public native void setMemory(Object o, long offset, long bytes, byte value); //从一个内存块复制到还有一个内存块
public native void copyMemory(Object srcBase, long srcOffset, Object destBase, long destOffset, long bytes); //获取值。无论java的訪问限制,其它有相似的getDouble,getLong,getChar等等
public native Object getObject(Object o, long offset); //设置值,无论java的訪问限制,其它有相似的putDouble,putLong,putChar等等
public native void putObject(Object o, long offset); //从一个给定的内存地址获取本地指针。假设不是allocateMemory方法的,结果将不确定
public native long getAddress(long address); //存储一个本地指针到一个给定的内存地址,假设地址不是allocateMemory方法的,结果将不确定
public native void putAddress(long address, long x); //该方法返回给定field的内存地址偏移量,这个值对于给定的filed是唯一的且是固定不变的
public native long staticFieldOffset(Field f); //报告一个给定的字段的位置。无论这个字段是private,public还是保护类型,和staticFieldBase结合使用
public native long objectFieldOffset(Field f); //获取一个给定字段的位置
public native Object staticFieldBase(Field f); //确保给定class被初始化,这往往须要结合基类的静态域(field)
public native void ensureClassInitialized(Class c); //能够获取数组第一个元素的偏移地址
public native int arrayBaseOffset(Class arrayClass); //能够获取数组的转换因子。也就是数组中元素的增量地址。 将arrayBaseOffset与arrayIndexScale配合使用, 能够定位数组中每一个元素在内存中的位置
public native int arrayIndexScale(Class arrayClass); //获取本机内存的页数。这个值永远都是2的幂次方
public native int pageSize(); //告诉虚拟机定义了一个没有安全检查的类,默认情况下这个类载入器和保护域来着调用者类
public native Class defineClass(String name, byte[] b, int off, int len, ClassLoader loader, ProtectionDomain protectionDomain); //定义一个类,可是不让它知道类载入器和系统字典
public native Class defineAnonymousClass(Class hostClass, byte[] data, Object[] cpPatches); //锁定对象,必须是没有被锁的
public native void monitorEnter(Object o); //解锁对象
public native void monitorExit(Object o); //试图锁定对象,返回true或false是否锁定成功,假设锁定,必须用monitorExit解锁
public native boolean tryMonitorEnter(Object o); //引发异常,没有通知
public native void throwException(Throwable ee); //CAS,相似的有compareAndSwapInt,compareAndSwapLong,compareAndSwapBoolean,compareAndSwapChar等等。
public final native boolean compareAndSwapObject(Object o, long offset, Object expected, Object x); // 该方法获取对象中offset偏移地址相应的整型field的值,支持volatile load语义。相似的方法有getIntVolatile,getBooleanVolatile等等
public native Object getObjectVolatile(Object o, long offset); //线程调用该方法,线程将一直堵塞直到超时。或者是中断条件出现。
public native void park(boolean isAbsolute, long time); //终止挂起的线程,恢复正常.java.util.concurrent包中挂起操作都是在LockSupport类实现的。也正是使用这两个方法,兴许将会把java.util.concurrent包相关的源代码分析整理出来。
public native void unpark(Object thread); //获取系统在不同一时候间系统的负载情况
public native int getLoadAverage(double[] loadavg, int nelems); //创建一个类的实例,不须要调用它的构造函数、初使化代码、各种JVM安全检查以及其它的一些底层的东西。即使构造函数是私有,我们也能够通过这种方法创建它的实例,对于单例模式。简直是噩梦,哈哈
public native Object allocateInstance(Class cls) throws InstantiationException;

sum.msic.Unsafe类有一个私有的实例:theUnsafe

private static final Unsafe theUnsafe = new Unsafe();

我们能够通过反射机制获取Unsafe实例,以下举一个简单的样例:

public class UnsafeTest {
private static Unsafe unsafe; public static void main(String[] args) throws Exception {
try {
//通过反射获取rt.jar下的Unsafe类
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
unsafe = (Unsafe) field.get(null);
Integer target = 12;
//compareAndSwapInt方法的属性各自是:目标对象实例,目标对象属性偏移量。当前预期值,要设的值.
//compareAndSwapInt方法是通过反射改动对象的值,详细改动对象以下那个值。能够通过偏移量。对象字段的偏移量能够通过objectFieldOffset获取
System.out.println(unsafe.compareAndSwapInt(target, 12, 11, 10));
System.out.println(target);
} catch (Exception e) {
System.out.println("Get Unsafe instance occur error" + e);
}
}
}

执行以上代码,设置Eclipse:

将Windows->Preferences->Java-Complicer->Errors/Warnings->Deprecated and restricted API,中的Forbidden references(access rules)设置为Warning,即能够编译通过。

最后:Unsafe类是没有安全保证,稍有疏忽或是使用不当,都可能造成JVM崩溃。

兴许将会整理一下java.util.concurrent包相关类的源代码分析,对于Unsafe各个方法的具体应用,将会具体分析。

并行编程(1) - sum.msic.Unsafe 一的更多相关文章

  1. 并行编程(2) - sum.msic.Unsafe 二

    整理了几个曾经从网上记录sum.msic.Unsafe类的演示样例.供大家參考: package com.fish.unsafe; import java.io.File; import java.i ...

  2. OpenMP共享内存并行编程详解

    实验平台:win7, VS2010 1. 介绍 平行计算机可以简单分为共享内存和分布式内存,共享内存就是多个核心共享一个内存,目前的PC就是这类(不管是只有一个多核CPU还是可以插多个CPU,它们都有 ...

  3. .NET并行编程1 - 并行模式

    设计模式——.net并行编程,清华大学出版的中译本. 相关资源地址主页面: http://parallelpatterns.codeplex.com/ 代码下载: http://parallelpat ...

  4. C#并行编程-PLINQ:声明式数据并行

    目录 C#并行编程-相关概念 C#并行编程-Parallel C#并行编程-Task C#并行编程-并发集合 C#并行编程-线程同步原语 C#并行编程-PLINQ:声明式数据并行 背景 通过LINQ可 ...

  5. C# IEnumerable,Lambda表达式和 Parallel并行编程的用法

    以前一直主要做C++和C方面的项目,对C#不太了解熟悉,但听说不难,也就一直没有在意学习C#方面的知识.今天有个C#项目,需要做些应用的扩展,同时修改一些bug.但看了C#代码,顿时觉得有些不适应了. ...

  6. 6.跑步者--并行编程框架 ForkJoin

    本文如果您已经了解一般并行编程知识.了解Java concurrent部分如ExecutorService等相关内容. 虽说是Java的ForkJoin并行框架.但不要太在意Java,当中的思想在其他 ...

  7. 转载 三、并行编程 - Task同步机制。TreadLocal类、Lock、Interlocked、Synchronization、ConcurrentQueue以及Barrier等

    随笔 - 353, 文章 - 1, 评论 - 5, 引用 - 0 三.并行编程 - Task同步机制.TreadLocal类.Lock.Interlocked.Synchronization.Conc ...

  8. .NET 并行编程——任务并行

    本文内容 并行编程 任务并行 隐式创建和运行任务 显式创建和运行任务 任务 ID 任务创建选项 创建任务延续 创建分离的子任务 创建子任务 等待任务完成 组合任务 任务中的异常处理 取消任务 Task ...

  9. .NET 并行编程——数据并行

    本文内容 并行编程 数据并行 环境 计算 PI 矩阵相乘 把目录中的全部图片复制到另一个目录 列出指定目录中的所有文件,包括其子目录 最近,对多线程编程,并行编程,异步编程,这三个概念有点晕了,之前我 ...

随机推荐

  1. Cracking the Coding Interview 5.2

    Given a(decimal -e.g. 3.72)number that is passed in as a string, print the binary representation. If ...

  2. WPF全球化与本地化

    当一个App需要推出多语言版本时,就需要使用到[全球化与本地化]服务. 原理及过程 资源文件中包含了所有的控件信息,通过导出这些控件信息,修改其对应的相关属性(比如TextBlock的Text属性)的 ...

  3. Codeforces Round #445

    ACM ICPC 每个队伍必须是3个人 #include<stdio.h> #include<string.h> #include<stdlib.h> #inclu ...

  4. MobX入门

    MobX入门 本文尝试解释MobX是如何运作的.我们将用MobX创建一个小案例.如果你正在找靠谱的MobX文档,可以去看官方文档. 什么是MobX 官方文档的解释:简洁,易扩展的状态管理.简单来说,M ...

  5. jq+mui 阻止事件冒泡

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name ...

  6. echarts 圆形图、柱状图

    首先引入echarts的js包 <script type="text/javascript" src="js/esl.js"></script ...

  7. es6学习 http://es6.ruanyifeng.com/

    基础学习   http://es6.ruanyifeng.com/  够了 1字符串 字符串的遍历器接口 for (let codePoint of 'foo') { console.log(code ...

  8. easyui的datetimebox时间格式化详解

    今天公司让用easyui的datetimebox组件,而且还要让格式化成大家通用的那种,网上搜了很多,但差不多都是复制黏贴的,最后请教了下螃蟹. 感谢螃蟹抽空给做了个例子,现在拿出来和大家分享下,效果 ...

  9. Verilog之openMSP430(1)

    openMSP430_IO interrupt Verilog file: omsp_gpio.v //================================================ ...

  10. IdentityServer4-HybridAndClientCredentials

    一.服务器 Client设置: new Client { ClientId = "mvc1", ClientName = "后台管理MVC客户端", Clien ...