一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - Java教程 - 一篇看懂Java中的Unsafe類

一篇看懂Java中的Unsafe類

2021-05-05 10:42Ye_yang Java教程

在閱讀AtomicInteger的源碼時,看到了這個類:sum.msic.Unsafe,之前從沒見過。所以花了點(diǎn)時間研究了下,下面這篇文章主要給大家介紹了關(guān)于Java中Unsafe類的相關(guān)資料,需要的朋友可以參考借鑒,下面來一起學(xué)習(xí)學(xué)習(xí)吧

前言

本文主要給大家介紹了關(guān)于java中unsafe類的相關(guān)內(nèi)容,分享出來供大家參考學(xué)習(xí),下面話不多說了,來一起看看詳細(xì)的介紹吧

1.unsafe類介紹

unsafe類是在sun.misc包下,不屬于java標(biāo)準(zhǔn)。但是很多java的基礎(chǔ)類庫,包括一些被廣泛使用的高性能開發(fā)庫都是基于unsafe類開發(fā)的,比如netty、hadoop、kafka等。

使用unsafe可用來直接訪問系統(tǒng)內(nèi)存資源并進(jìn)行自主管理,unsafe類在提升java運(yùn)行效率,增強(qiáng)java語言底層操作能力方面起了很大的作用。

unsafe可認(rèn)為是java中留下的后門,提供了一些低層次操作,如直接內(nèi)存訪問、線程調(diào)度等。

 官方并不建議使用unsafe。

下面是使用unsafe的一些例子。

1.1實(shí)例化私有類

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import java.lang.reflect.field;
import sun.misc.unsafe;
public class unsafeplayer {
 public static void main(string[] args) throws exception {
 //通過反射實(shí)例化unsafe
 field f = unsafe.class.getdeclaredfield("theunsafe");
 f.setaccessible(true);
 unsafe unsafe = (unsafe) f.get(null);
 //實(shí)例化player
 player player = (player) unsafe.allocateinstance(player.class);
 player.setname("li lei");
 system.out.println(player.getname());
 }
}
 
class player{
 private string name;
 private player(){}
 public string getname() {
 return name;
 }
 public void setname(string name) {
 this.name = name;
 }
}

1.2cas操作,通過內(nèi)存偏移地址修改變量值

java并發(fā)包中的synchronousqueue中的transferstack中使用cas更新棧頂。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/ unsafe mechanics
private static final sun.misc.unsafe unsafe;
private static final long headoffset;
static {
 try {
 unsafe = sun.misc.unsafe.getunsafe();
 class<?> k = transferstack.class;
 headoffset = unsafe.objectfieldoffset
  (k.getdeclaredfield("head"));
 } catch (exception e) {
 throw new error(e);
 }
}
//棧頂
volatile snode head;
//更新棧頂
boolean cashead(snode h, snode nh) {
 return h == head &&
 unsafe.compareandswapobject(this, headoffset, h, nh);
}

1.3直接內(nèi)存訪問

unsafe的直接內(nèi)存訪問:用unsafe開辟的內(nèi)存空間不占用heap空間,當(dāng)然也不具有自動內(nèi)存回收功能。做到像c一樣自由利用系統(tǒng)內(nèi)存資源。

2.unsafe類源碼分析

unsafe的大部分api都是native的方法,主要包括以下幾類:

1)class相關(guān)。主要提供class和它的靜態(tài)字段的操作方法。

2)object相關(guān)。主要提供object和它的字段的操作方法。

3)arrray相關(guān)。主要提供數(shù)組及其中元素的操作方法。

4)并發(fā)相關(guān)。主要提供低級別同步原語,如cas、線程調(diào)度、volatile、內(nèi)存屏障等。

5)memory相關(guān)。提供了直接內(nèi)存訪問方法(繞過java堆直接操作本地內(nèi)存),可做到像c一樣自由利用系統(tǒng)內(nèi)存資源。

6)系統(tǒng)相關(guān)。主要返回某些低級別的內(nèi)存信息,如地址大小、內(nèi)存頁大小。

2.1class相關(guān)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//靜態(tài)屬性的偏移量,用于在對應(yīng)的class對象中讀寫靜態(tài)屬性
public native long staticfieldoffset(field f);
 
public native object staticfieldbase(field f);
//判斷是否需要初始化一個類
public native boolean shouldbeinitialized(class<?> c);
//確保類被初始化
public native void ensureclassinitialized(class<?> c);
//定義一個類,可用于動態(tài)創(chuàng)建類
public native class<?> defineclass(string name, byte[] b, int off, int len,
     classloader loader,
     protectiondomain protectiondomain);
//定義一個匿名類,可用于動態(tài)創(chuàng)建類
public native class<?> defineanonymousclass(class<?> hostclass, byte[] data, object[] cppatches);

2.2object相關(guān)

java中的基本類型(boolean、byte、char、short、int、long、float、double)及對象引用類型都有以下方法。

?
1
2
3
4
5
6
//獲得對象的字段偏移量
public native long objectfieldoffset(field f);
//獲得給定對象地址偏移量的int值
public native int getint(object o, long offset);
//設(shè)置給定對象地址偏移量的int值
public native void putint(object o, long offset, int x);
?
1
2
3
//創(chuàng)建對象,但并不會調(diào)用其構(gòu)造方法。如果類未被初始化,將初始化類。
public native object allocateinstance(class<?> cls)
 throws instantiationexception;

2.3數(shù)組相關(guān)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/**
 * report the offset of the first element in the storage allocation of a
 * given array class. if {@link #arrayindexscale} returns a non-zero value
 * for the same class, you may use that scale factor, together with this
 * base offset, to form new offsets to access elements of arrays of the
 * given class.
 *
 * @see #getint(object, long)
 * @see #putint(object, long, int)
 */
//返回數(shù)組中第一個元素的偏移地址
public native int arraybaseoffset(class<?> arrayclass);
//boolean、byte、short、char、int、long、float、double,及對象類型均有以下方法
/** the value of {@code arraybaseoffset(boolean[].class)} */
public static final int array_boolean_base_offset
 = theunsafe.arraybaseoffset(boolean[].class);
 
/**
 * report the scale factor for addressing elements in the storage
 * allocation of a given array class. however, arrays of "narrow" types
 * will generally not work properly with accessors like {@link
 * #getbyte(object, int)}, so the scale factor for such classes is reported
 * as zero.
 *
 * @see #arraybaseoffset
 * @see #getint(object, long)
 * @see #putint(object, long, int)
 */
//返回數(shù)組中每一個元素占用的大小
public native int arrayindexscale(class<?> arrayclass);
 
//boolean、byte、short、char、int、long、float、double,及對象類型均有以下方法
/** the value of {@code arrayindexscale(boolean[].class)} */
public static final int array_boolean_index_scale
 = theunsafe.arrayindexscale(boolean[].class);

通過arraybaseoffset和arrayindexscale可定位數(shù)組中每個元素在內(nèi)存中的位置。

2.4并發(fā)相關(guān)

 2.4.1cas相關(guān)

cas:compareandswap,內(nèi)存偏移地址offset,預(yù)期值expected,新值x。如果變量在當(dāng)前時刻的值和預(yù)期值expected相等,嘗試將變量的值更新為x。如果更新成功,返回true;否則,返回false。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
//更新變量值為x,如果當(dāng)前值為expected
//o:對象 offset:偏移量 expected:期望值 x:新值
public final native boolean compareandswapobject(object o, long offset,
       object expected,
       object x);
 
public final native boolean compareandswapint(object o, long offset,
      int expected,
      int x);
 
public final native boolean compareandswaplong(object o, long offset,
      long expected,
      long x);

從java 8開始,unsafe中提供了以下方法:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
//增加
public final int getandaddint(object o, long offset, int delta) {
 int v;
 do {
 v = getintvolatile(o, offset);
 } while (!compareandswapint(o, offset, v, v + delta));
 return v;
}
 
public final long getandaddlong(object o, long offset, long delta) {
 long v;
 do {
 v = getlongvolatile(o, offset);
 } while (!compareandswaplong(o, offset, v, v + delta));
 return v;
}
//設(shè)置
public final int getandsetint(object o, long offset, int newvalue) {
 int v;
 do {
 v = getintvolatile(o, offset);
 } while (!compareandswapint(o, offset, v, newvalue));
 return v;
}
 
public final long getandsetlong(object o, long offset, long newvalue) {
 long v;
 do {
 v = getlongvolatile(o, offset);
 } while (!compareandswaplong(o, offset, v, newvalue));
 return v;
}
 
public final object getandsetobject(object o, long offset, object newvalue) {
 object v;
 do {
 v = getobjectvolatile(o, offset);
 } while (!compareandswapobject(o, offset, v, newvalue));
 return v;

2.4.2線程調(diào)度相關(guān)

?
1
2
3
4
5
6
7
8
9
10
//取消阻塞線程
public native void unpark(object thread);
//阻塞線程
public native void park(boolean isabsolute, long time);
//獲得對象鎖
public native void monitorenter(object o);
//釋放對象鎖
public native void monitorexit(object o);
//嘗試獲取對象鎖,返回true或false表示是否獲取成功
public native boolean trymonitorenter(object o);

2.4.3volatile相關(guān)讀寫

java中的基本類型(boolean、byte、char、short、int、long、float、double)及對象引用類型都有以下方法。

?
1
2
3
4
5
6
7
//從對象的指定偏移量處獲取變量的引用,使用volatile的加載語義
//相當(dāng)于getobject(object, long)的volatile版本
public native object getobjectvolatile(object o, long offset);
 
//存儲變量的引用到對象的指定的偏移量處,使用volatile的存儲語義
//相當(dāng)于putobject(object, long, object)的volatile版本
public native void putobjectvolatile(object o, long offset, object x);
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
 * version of {@link #putobjectvolatile(object, long, object)}
 * that does not guarantee immediate visibility of the store to
 * other threads. this method is generally only useful if the
 * underlying field is a java volatile (or if an array cell, one
 * that is otherwise only accessed using volatile accesses).
 */
public native void putorderedobject(object o, long offset, object x);
 
/** ordered/lazy version of {@link #putintvolatile(object, long, int)} */
public native void putorderedint(object o, long offset, int x);
 
/** ordered/lazy version of {@link #putlongvolatile(object, long, long)} */
public native void putorderedlong(object o, long offset, long x);

2.4.4內(nèi)存屏障相關(guān)

java 8引入 ,用于定義內(nèi)存屏障,避免代碼重排序。

?
1
2
3
4
5
6
//內(nèi)存屏障,禁止load操作重排序,即屏障前的load操作不能被重排序到屏障后,屏障后的load操作不能被重排序到屏障前
public native void loadfence();
//內(nèi)存屏障,禁止store操作重排序,即屏障前的store操作不能被重排序到屏障后,屏障后的store操作不能被重排序到屏障前
public native void storefence();
//內(nèi)存屏障,禁止load、store操作重排序
public native void fullfence();

2.5直接內(nèi)存訪問(非堆內(nèi)存)

allocatememory所分配的內(nèi)存需要手動free(不被gc回收)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//(boolean、byte、char、short、int、long、float、double)都有以下get、put兩個方法。
//獲得給定地址上的int值
public native int getint(long address);
//設(shè)置給定地址上的int值
public native void putint(long address, int x);
//獲得本地指針
public native long getaddress(long address);
//存儲本地指針到給定的內(nèi)存地址
public native void putaddress(long address, long x);
 
//分配內(nèi)存
public native long allocatememory(long bytes);
//重新分配內(nèi)存
public native long reallocatememory(long address, long bytes);
//初始化內(nèi)存內(nèi)容
public native void setmemory(object o, long offset, long bytes, byte value);
//初始化內(nèi)存內(nèi)容
public void setmemory(long address, long bytes, byte value) {
 setmemory(null, address, bytes, value);
}
//內(nèi)存內(nèi)容拷貝
public native void copymemory(object srcbase, long srcoffset,
    object destbase, long destoffset,
    long bytes);
//內(nèi)存內(nèi)容拷貝
public void copymemory(long srcaddress, long destaddress, long bytes) {
 copymemory(null, srcaddress, null, destaddress, bytes);
}
//釋放內(nèi)存
public native void freememory(long address);

2.6系統(tǒng)相關(guān)

?
1
2
3
4
5
6
7
8
//返回指針的大小。返回值為4或8。
public native int addresssize();
 
/** the value of {@code addresssize()} */
public static final int address_size = theunsafe.addresssize();
 
//內(nèi)存頁的大小。
public native int pagesize();

3.參考資料

 說一說java中的unsafe類

java魔法類:sun.misc.unsafe

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對服務(wù)器之家的支持。

原文鏈接:https://www.cnblogs.com/yeyang/p/9074894.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 麻豆网站在线免费观看 | 色综合亚洲天天综合网站 | 欧美一二区视频 | 99久久999久久久综合精品涩 | 丁香六月色婷婷综合网 | 按摩椅play啊太快了h | 欧美在线一级片 | 久久AV喷吹AV高潮欧美 | 87影院在线观看视频在线观看 | 亚洲va欧美va天堂v国产综合 | 国产精品久久久精品视频 | 高贵女王调奴vk | 91九色porny国产美女一区 | 欧美激烈精交gif动态图18p | 9966久久精品免费看国产 | 国产欧美日韩精品在线 | 午夜神器18以下不能进免费 | 久久re视频这里精品一本到99 | 国产三级精品久久三级国专区 | 古装一级无遮挡毛片免费观看 | 国产成人精品视频一区二区不卡 | 免费观看美景之屋 | 秋霞理论一级在线观看手机版 | 免费看男女做好爽好硬视频 | 成人网免费视频 | 亚洲欧美自偷自拍另类小说 | 国产va欧美va在线观看 | 精品久久久久免费极品大片 | 天天做天天爰夜夜爽 | 91香蕉依人综合久久 | 99pao在线视频精品免费 | 亚洲第一福利视频 | 四大美女思春艳史片 | 亚洲图片 自拍偷拍 | 拍拍叫痛的无挡视频免费 | 日本一卡二卡3卡四卡网站精品 | 超高清欧美同性videos | 国产成人盗摄精品 | 免费看国产一级片 | 美女扒开两腿露出尿口的视频 | 久久伊人影视 |