背景:
閱讀新聞
.NET跨平臺實踐:用C#開發Linux守護進程
[日期:2016-04-05]
來源:Linux社區
作者:宇內流云
[字體:大 中 小]
Linux守護進程(Daemon)是Linux的后臺服務進程,它脫離了與控制終端的關聯,直接由Linux init進程管理其生命周期,即使你關閉了控制臺,daemon也能在后臺正常工作。
一句話,為Linux開發與控制臺無關的,需要在后臺長時間不間斷運行的“服務程序”,Daemon技術是非常重要的。
Daemon程序一般用c/c++開發。不過,我今天要講的,不是怎么用c/c++開發daemon,而是用C#!
一,創建Daemon程序:
用VS新建一個控制臺項目,假設名稱是MyDaemon,輸入下邊的代碼:
using System.Runtime.InteropServices;
using System.Threading;
namespace MyDaemon
{
class Program
{
static void Main(string[] args)
{
int pid= fork();
if (pid !=0) exit(0);
//設置“會話組長”,與父進程脫離
setsid();
pid = fork();
if (pid !=0) exit(0);
//已經進程“守護進程”工作狀態了!
//關閉所有打開的文件描述符
int max=open("/dev/null", 0);
for (var i=0; i <=max; i++) { close(i); }
//重設文件掩模
umask(0);
//執行你的程序過程
DaemonMain(args);
}
///
/// Daemon工作狀態的主方法
///
///
static void DaemonMain(string[] aargs)
{
//你的工作代碼...
//daemon時,控制臺輸入輸出流已經關閉
//請不要再用Console.Write/Read等方法
//阻止daemon進程退出
while (true)
{ Thread.Sleep(1000); }
}
[DllImport("libc", SetLastError=true)]
static extern int fork();
[DllImport("libc", SetLastError=true)]
static extern int setsid();
[DllImport("libc", SetLastError=true)]
static extern int umask(int mask);
[DllImport("libc", SetLastError=true)]
static extern int open([MarshalAs(UnmanagedType.LPStr)]string pathname, int flags);
[DllImport("libc", SetLastError=true)]
static extern int close(int fd);
[DllImport("libc", SetLastError=true)]
static extern int exit(int code);
}
}
然后編譯為 MyDaemon.exe。
二,部署和運行:
.net 程序在linux運行,一般都會使用mono這個.net框架,不過,為了簡單方便,我這里使用 AnyExec來運行這個程序(關于AnyExec,請參閱:不裝mono,你的.NET程序照樣可以在Linux上運行!)。
1,把 MyDeamon.exe放到anyexec的app文件夾;
2,把 "any"這個程序復制為 MyDeamon;
3,運行:見證神奇的時間到了!請你在linux控制終端上輸入: http://www.linuxidc.com/Linux/2016-04/MyDaemon,哈哈,怎么沒有反應? 其實,不是沒有反應,是你這個 MyDaemon程序已經在后臺跑起來了!
輸入 “ps -ef”,看看!
看到那個 MyDaemon了吧!這次運行的PID是11618,父進程是的PID是1,1是誰?linux init!
4,退出daemon程序:daemon程序不會與控制臺輸入輸出進行交互,所以,用Console.ReadLine之類的方法控制進程的退出是不現實的。那么,怎么關閉這個在后臺運行的 daemon呢? 最簡辦法就是用ps -ef查出這個進程的PID號,然后用kill命令終止它。比如當前運行的這個 mydaemon的PID號是 11618,你只需要輸入 kill -9 11618,就能終止它的運行。
(本文為宇內流云原創,經查,暫沒發現網上有類似的技術文章,歡迎轉載,但不要把作者的名字給弄丟了)
本文永久更新鏈接地址:http://www.linuxidc.com/Linux/2016-04/129842.htm
Swift函數和閉包
JVM-類加載機制
相關資訊
Linux守護進程 C#開發Linux守護進程
Linux守護進程 (09/19/2015 15:01:04)
Linux下的守護進程 (01/25/2015 11:46:45)
Linux系統守護進程詳解ntsysv 可以 (09/29/2013 08:57:56)
Linux 的進程組、會話、守護進程 (04/04/2015 11:16:46)
Linux守護進程學習 (01/04/2014 19:15:04)
Linux編程---守護進程 (01/04/2013 09:35:30)
本文評論
查看全部評論 (0)
表情:
姓名:
匿名
字數
同意評論聲明
評論聲明
尊重網上道德,遵守中華人民共和國的各項有關法律法規
承擔一切因您的行為而直接或間接導致的民事或刑事法律責任
本站管理人員有權保留或刪除其管轄留言中的任意內容
本站有權在網站內轉載或引用您的評論
參與本評論即表明您已經閱讀并接受上述條款
最新資訊
CentOS 6.4下雙網卡bond配置
CentOS6.x雙網卡采用主-備份策略綁定(bond
ORA-30036故障解決方法案例
ORA-03114: 未連接到 ORALCE 解決方法案例
Oracle RAC系統內存無法釋放解決
Oracle Goldengate在HP平臺裸設備文件系統
OGG升級運行ggsic報Unable to find library
Linux vi命令大全
VMware虛擬機主機模式下與主機互ping通
Linux內核中container_of函數詳解
背景:
閱讀新聞
JVM-類加載機制
[日期:2016-04-05]
來源:Linux社區
作者:lrh-xl
[字體:大 中 小]
虛擬機類加載機制
虛擬機把描述的類的數據從class文件加載到內存后,并對數據進行校驗,轉換解析和初始化,最終形成可以被虛擬機直接使用的Java類型,這就是虛擬機的類加載機制。
類加載的時機
類被加載到虛擬機內存開始,到卸載出內存為止。它的整個生命周期包括:類加載(Loading),驗證(Verification),準備(Preparation),解析(Resolution),初始化(Initialization),使用(Using)和卸載(Unloading)7個階段。其中驗證,準備,解析3個部分統稱為連接(Linking)。
虛擬機規范嚴格規定了有且僅有5種情況必須立即對類進行“初始化”:
1.遇到new , getstatic , putstatic 或involvestatic這4條字節碼指令時,如果類沒有進行過初始化,則需要先觸發其初始化。
2.使用java.lang.reflect包的方法對類進行反射調用的時候,如果類沒有進行過初始化,則需要先觸發其初始化。
3.當初始化一個類的時候,如果發現其父類還沒有進行過初始化,則需要先觸發其父類的初始化。
4.當虛擬機啟動時,用戶需要指定一個要執行的主類(包含main方法的類),虛擬機會先初始化這個類。
5.當使用JDK1.7的動態語言支持時,如果java.lang.invoke.MethodHeadle實例,最后的解析結果REF_getstatic , REF_putstatic , REF_invokestatic的方法句柄,并且這個方法句柄所對應的類沒有進行過初始化,則需要先觸發其初始化。
類加載的過程
一、加載
(1)在加載階段,虛擬機需要完成以下3件事:
1.通過一個類的全限定名來獲取定義此類的二進制字節流
2.將這個字節流所代表的靜態存儲結構結構轉化為方法區的運行時數據結構
3.在內存中生成一個代表這個類的java.lang.class對象,作為方法區這個類的各種數據的訪問入口
(2)數組類本身不通過類加載器創建,他是由Java虛擬機直接創建的。
一個數組類創建過程遵循以下規則:
1.如果數組的組件類型(Component Type , 指的是數組去掉一個維度的類型)是引用類型,那就遞歸采用上面介紹的加載過程去加載這個組件類型,數組將在加載該數組組件類型的類加載器的類名稱空間上唄標識。
2.如果數組的組件類型不是7引用類型,Java虛擬機將會把數組標記為與引導類加載器關聯。
3.數組類的可見性與它的組件類型的可見性一致,如果組件類型不是引用類型,需要數組類的可見性將 默認為public
二、驗證
驗證是連接階段的第一步,這一階段的目的是為了確保class文件的字節流包含的信息符合當前虛擬機的要求,并且不會危害虛擬機本省的安全。
驗證階段大致上會完成以下4個階段的檢驗動作:文件格式驗證、元數據驗證、字節碼驗證、符號引用驗證
(1 ) 文件格式驗證
1.第一階段要驗證字節流是否符合class文件格式的規范,并且能被當前版本的虛擬機處理。
2.中油通過了這個階段的驗證后,字節流才會進入內存的方法區中進行存儲,所以后面的3個驗證階段全部是基于方法區的存儲結構進行的,不會直接操作字節碼。
(2 ) 元數據驗證
1.第二階段是對字節碼描述的信息進行語義分析,以確保其描述的信息符合Java語言規范的要求。
2.第二階段的主要目的是對類的元數據信息進行語義化驗,保證不存在不符合Java語言規范的元數據信息
(3 ) 字節碼驗證
1.督三階段是整個驗證過程中最復雜的一個階段,主要目的是通過數據流和控制流分析,確定程序語義是合法的,符合邏輯的。這個階段將對類的方法體進行校驗分析。保證被校驗類的方法運行時不會做出危害虛擬機安全的時間。
2.例如:保證任意時刻操作數棧的數據類型與指令代碼序列都能配合工作。保證跳轉到方法體以外的字節碼指令上。
(4 ) 符號引用驗證
1.最后一個驗證階段的檢驗發生在虛擬機將符號引用轉化為直接引用的時候,這個轉化動作將在連接階段的第三階段——解析階段中發生。符號引用驗證可以看做是對類自身以外的信息進行匹配性校驗。
2.例如:符號引用中通過字符串描述中的全限定名是否能找到對應的類。在特定類中是否存在符合方法的字段描述符以及簡單名稱所描述的方法和字段
3.符號引用驗證的目的是確定解析動作能正常執行,如果無法通過符號引用驗證,那么將會拋出java.lang.IncompatibleClassChangeError異常的子類
三、準備
準備階段是正式為類變量 分配內存并設置類變量初始值的階段,這些變量所使用的內存將在方法區中進行分配。
四、解析
(1)解析階段是虛擬機將常量池內的符號引用替換為直接引用的過程。
1.符號引用(symbolic Reference):符號引用逸一組符號來描述所引用的目標,符號可以是任何形式的字面量,只要使用 時能無歧義地定位到引用目標即可。符號引用與虛擬機實現的內存布局無關,引用的目標并不一定已經加載到內存中。各種虛擬機實現的內存布局可以各不相同,但是它們能接受的符號引用必須是一致的,因為符號引用的字面量形式明確定義在Java虛擬機規范中的class文件格式中。
2.直接引用(Direct Reference):直接引用可以是直接指向目標的指針。相對偏移量或是一個能間接定位到目標的句柄。直接引用是和虛擬機實現的內存布局相關的,同一個符號引用在不同的虛擬機實例上翻譯出來的直接引用一般不會相同,如果有了直接引用那引用的目標必定已經在內存中存在。
(2)虛擬機規范中并未規定解析階段發生的具體時間,只要求了執行anewarray,checkcast,getfield,getstatic,instanceof,invokedynamic,invokeinterface,invokespecial,invokestatic,invokevirtual,ldc,ldc_w,multianewarray,new,putField和putstatic這16個用于操作符號引用的字節碼指令之前,先過它們所使用的符號引用進行解析。
(3)解析動作主要針對類或接口,字段,類方法,接口方法,方法類型,方法句柄和調用點限定符7類符號引用進行。
(4)類或接口的解析
虛擬機完成整個解析的過程需要以下3個步驟
1)如果c不是一個數組類型,那虛擬機將會把代表N的全限定名傳遞給D的類加載器去加載這個類C。在加載過程中,由于元數據驗證,字節碼驗證的需要,又可能觸發其他相關的類的加載動作。
2)如果C是一個數組類型,并且數組的元素類型為對象,那將會按以上的規則加載數組類型。如果N的描述符如前面所假設的形式,需要加載元素的類型,接著由虛擬機生成一個代表此數組維度和元素的數組對象。
3)如果上面的步驟沒有出現任何異常,那么C在虛擬機中實際上已經成為一個有效的類或接口了,但在解析完成之后還要進行符號引用驗證,確認D是否是具備對C的訪問權限。
(5)字段解析
(6)類方法解析
(7)接口方法解析
五、初始化
1.類初始化階段是類加載過程的最后一步
2.在準備階段,變量已經賦過一次系統要過的初始值,而在初始化階段,則根據程序員制定的主觀去初始化變量和其他資源,或者可以從另外一個角度來表達:初始化階段是執行類構造器()方法的過程。
3.()方法是由編譯器自動收集類中的所有類變量的賦值動作和靜態語句塊(static{}塊)中的語句合并產生的,編譯器收集的順序是由語句在源文件中出現的順序所決定的,靜態語句塊只能訪問到定義在靜態語句塊之前的變量,定義在它之后的變量,在前面的靜態語句塊可以賦值,但是不能訪問。
4.()方法與類的構造函數不同,它不需要顯式地調用父類構造器,虛擬機會保證在子類的()方法執行之前,父類的()方法已經執行完畢。因此在虛擬機中第一個被執行的()方法的類肯定有java.lang.object。
5.由父類的()方法先執行,也就意味著父類中定義的靜態語句塊要優先于子類的變量賦值操作。
6.()方法對于類或接口來說并不是必須的,如果一個類中沒有靜態語句塊,也沒有對變量的賦值操作,那么編譯器可以不為這個類生成()方法
7.虛擬機會保證一個類的()方法在多個線程環境中正確地加鎖,同步。
類加載器
一、類與類加載器
對于任意一個類,需要由加載它的加載器和這個類本身一同確立其在Java虛擬機中的唯一性,每一個類加載器,都擁有一個獨立的類名稱空間。
二、雙親委派模型
(1)從Java虛擬機的角度來講,只存在兩種不同的類加載器:一種是啟動類加載器(Bootstrap Class ClassLoader),這個類加載器使用C++語言實現是Java虛擬機自動的一部分;另一種就是所有其他的類加載器,這些類加載器都由Java語言實現,獨立于虛擬機外部,并且全都是繼承自抽象類java.lang.classLoader.
(2)細分:啟動類加載器(Bootstrap ClassLoader)
擴展類加載器(Extension ClassLoadert)
應用程序類加載器(Application ClassLoader)[系統類加載器]
(3)雙親委派模型工作過程:
如果一個類加載器收到了類加載器的請求,它首先不會自己去嘗試加載這個類,而是把這個請求委派給父類加載器去完成,每一個層次的類加載器都是如此,因此所有的加載請求最終都應該傳送到頂層類加載器中只有當父類加載器反饋自己無法完成這個類加載請求時,子類加載器才會嘗試自己去加載。
本文永久更新鏈接地址:http://www.linuxidc.com/Linux/2016-04/129843.htm
.NET跨平臺實踐:用C#開發Linux守護進程
JVM-字節碼指令
相關資訊
JVM JVM類加載機制 JVM加載機制
JVM 運行時數據區域 (今 11:45)
JVM上的確定性執行機制 (05月12日)
JVM垃圾回收機制 (03月20日)
JVM類加載機制 (06月03日)
JVM虛擬機結構與機制 (04月17日)
JVM很重嗎? (03月14日)
本文評論
查看全部評論 (0)
表情:
姓名:
匿名
字數
同意評論聲明
評論聲明
尊重網上道德,遵守中華人民共和國的各項有關法律法規
承擔一切因您的行為而直接或間接導致的民事或刑事法律責任
本站管理人員有權保留或刪除其管轄留言中的任意內容
本站有權在網站內轉載或引用您的評論
參與本評論即表明您已經閱讀并接受上述條款
最新資訊
JVM 運行時數據區域
MySQL日志文件詳述
MySQL一致性非鎖定讀和鎖定讀
Spark-2.2.0安裝和部署詳解
Scala-2.11.7安裝筆記
配置SSH免密碼登錄
Hadoop 2.7.2集群搭建詳解
Google發布Tensor2Tensor for TensorFlow
解決百度BMR的Spark集群開啟slaves結點的問
Redhat 7.2 中文顯示及中文輸入法設置
背景:
閱讀新聞
JVM-字節碼指令
[日期:2016-04-05]
來源:Linux社區
作者:lrh-xl
[字體:大 中 小]
Java虛擬機字節碼指令
了解了class文件,我覺得就很有必要去了解一下JVM中的字節碼指令,那樣堆class文件以及JVM運行機制也后很大的幫助.
Java虛擬機的指令由一個字節長度的,代表著某種特定操作含義的數字(稱為操作碼,Opcode)以及跟隨其后的零至多個代表所需參數(稱為操作數,Oprands)而構成.由于Java虛擬機采用面向操作數棧而不是寄存器的架構,所以大多參數的指令都不包含操作數,只有一個操作碼.
字節碼指令的一些特性
由于限制了Java虛擬機操作碼的長度為一個字節(0~255),這意味著指令集的操作碼總數不可能超過256條.
由于class文件格式放棄了編譯后的操作數長度對齊,這意味著虛擬機處理那些超過一個字節數據的時候,不得不在運行時從字節中重建出具體數據的結構.如果要將一個16位長度的無符號整數,使用兩個無符號字節存儲起來(將它們命名為byte1和byte2),那它們的值應該是這樣的:(byte<<8)| byte2 .這種操作在某種程度上會導致解釋執行字節碼的時候會損失一些性能.但這樣做的優勢也是非常明顯的,放棄了操作數長度對齊,就意味著可以省略很多填充和間隔符號:用一個字節來表示操作碼,也是為了盡可能獲得短小精干的編譯代碼.
字節碼指令與數據類型
對于大部分與數據類型相關的字節碼指令它們的操作碼助記符中都有特殊特的字符來表明專門為哪種數據類型服務:i:代表int,l代表long,s代表short,b代表byte,c代表char,f代表float,d代表double,a代表reference.
Java虛擬機的指令集對于特定的操作只提供了有限的類型相關指令去支持它,換句話說,指令集將會故意被設計成非完全獨立的Java虛擬機規范中把這種特性稱為"Not Orthpogoal".即并非每種操作都有對應的指令.有一些單獨的指令可以在必要的時候來將一些不支持的類型轉換成為可被支持的類型.
加載和存儲指令
加載和存儲指令用于將數據在棧幀中的局部變量和操作數之間來回傳輸.
將一個局部變量加載到操作棧:ilaod , ioload,llaod , llaod,float,float,double,double,aload,aload.
將一個數據從操作數棧存儲到局部變量表:istore,istore,lstore,lstore,fstore.fstore,dstore,dstore,astore,asotre.
將一個常量加載到數據棧:bipush,sipush,ldc,ldc_w,ldc2_w,aconst_null,iconst_ml,iconst_,lconst_,fconst_,dconst_
擴充局部變量表訪問索引的指令:wide
運算指令
運算或算術指令用于對兩個操作數棧上的值進行某種特定運算,并把結果重新存入到操作棧頂.
大體上算術指令可以分為兩種:對整型數據進行運算的指令對浮點數據進行運算的指令.無論是哪種算術指令,都使用Java虛擬機的數據類型,由于沒有直接支持byte,short,char和boolean類型的算術指令,對于這類數據的運算應使用操作int類型的指令代替.
加法指令:iadd,ladd,fadd,dadd
減法指令:isub,lsub,fsub,dsub
乘法指令:imul,lmul,fmul,dmul
求余指令:irem,lrem,frem,drem
求反指令:ineg,lneg,fneg,dneg
移位指令:ishl.ishr,lshl,lshr,lushr
按位或指令:ior,lor
按位與指令:iand,land]
按位異或指令:ixor,lxor
局部變量自增指令:iinc
比較指令:dcmpy,dcmpl,fcmpg,fsmpyl,lcomp
Java虛擬機要求在進行浮點數運算時,所有的運算結果都必須舍入到適當的精度,非精確的結果必須舍入為可被表示的最接近的精確值.如果有兩種可表示的形式與該值一樣接近,將優先選擇最低有效位為零的,稱為向最近數舍入模式.
在把浮點數轉換為整數時,Java虛擬機使用IEEE754規范中的向零舍入模式,這中模式的舍入結果會導致數字被截斷,所有小數部分的有效字節都會被丟棄掉.向零舍入模式將在目標數值類型與該數值類型中選擇一個最接近但是不大于原數值的數字來作為最精確的舍入結果.
Java虛擬機在處理浮點數運算時,不會拋出任何運行時異常,當一個操作產生溢出時,將會使用有符號的無窮大來表示,如果某個操作結果沒有明確的數學定義的話,將會使用NaN值來表示,所有使用NaN值作為操作數的算術運算,結果都會返回NaN.
在對long類型數值進行比較時,虛擬機采用帶符號的比較方式,而對浮點數值,進行比較時(dcmpy,dcmpl,fcmpg,fcmpl),虛擬機會采用IEEE754規范所定義的無信號比較(Nonsignaling Conparions)方式.
類型轉換指令
類型轉換指令可以將兩種不同的數值類型進行相互轉換
Java直接支持(即轉換時無需顯示進行轉換指令)以下數值類型的寬化類型轉化(即范圍類型向大范圍類型的安全轉化):
1.int -->long , float , double
2.long -->float , double
3.float -->double
處理窄化類型轉換時,必須顯示的使用轉換指令來完成,這些轉換指令包括:i2b , i2c , i2s , l2i , f2c , d2i , d2l , d2f.窄化類型轉換可能會導致轉換結果產生不同的正負號,不同的數量級的情況,轉換可能會導致數值精度丟失.
將一個浮點型數值窄化為整型類型(int 或long)的時候,將遵循一下轉換規則
?如果浮點值是NaN,那轉換結果就是int或long類型的0.
?如果浮點值不是無窮大的話,浮點值使用向零舍入模式取整,獲得整數v.如果v在目標類型的表示范圍之內,轉換結果就是v.
?否則,將根據v的符號,轉換為一個T所能表示的最大會最小正數.
對象創建與訪問指令
指令:
?創建類實例的指令:new
?創建數組得到指令:newarray , anewarray , multianewarray
?訪問類字段(static 字段,或者稱為類變量)和實例字段(非static 字段,或者稱為實例變量)的指令:getfield , putfield , getstatic , putstatic\
?把一個數組元素加載到操作數棧的指令:baload , caload , saload , iaload , laload , faload , daload , aaload
?將一個操作數棧的值存儲到數組元素中的指令:bastore , castore , sastore , iastore , fastore , dastore , aastore
?取數組長度的指令:arraylength
?檢查類實例類型的指令:instanceof , checkcast
操作數棧管理指令
Java虛擬機提供了一些直接操作操作數的指令:
?操作數棧的棧頂一個或兩個元素出棧:pop , po2
?復制棧頂一個或兩個元素并將復制值或雙份值重新壓入棧頂:dup ,dup2,duo_x1,dup_x2,dup2_x2
?將棧最頂端的兩個數值交換:swap
控制轉移指令
控制轉移指令可以讓Java虛擬機有條件的從指定的位置而不是控制轉移指令的下一條指令繼續執行程序。可以認為控制轉移指令就是在有條件或無條件的修改PC寄存器的值。
控制轉移指令:
?條件分支:ifeq,iflt,ifne,ifge,ifgt,ifnull,ifnonnull,if_icmpeq,if_icmpne,if_icmplt,if_cmpgt,if_icmpge,if_cmpge,if_icmpeq,if_acmpne
?復合條件分支:tableswitch,lookupswitch
?無條件分支:goto,goto_w,jsr,jsr_w,ret
方法調用和返回指令
invokevirtual指令用于調用對象德邦實例方法,根據對象的實體的類型進行分派(虛方法分派),也就是Java語言中最常見的方法分派方式。
invokeinterface指令用于調用接口方法,它會在運行時搜索一個實現了這個接口方法的對象找出適合的方法進行調用。
invokespecial指令用于調用一些需要特殊處理的實例方法,包括實例初始化方法,私有方法和父類方法
involvestatic指令用于調用類的方法(static方法)
invokedynamic指令用于在運行時動態解析出調用點限定符所引用的方法,并執行該方法
前面4條調用指令的分派邏輯都固化在Java虛擬機的內部,而invokedynamic指令的分派邏輯是由用戶設定的引導方法決定的
異常處理指令
在Java虛擬機中處理異常catch語句不是由字節碼指令來實現的,而是用異常表來完成的。
在Java程序中顯式拋出異常的操作(throw語句)都是由athrow來實現的,除了用throw語句顯式拋出異常的情況之外,Java虛擬機規范還規定了許多運行時異常會在其他Java虛擬機指令檢測到異常狀況時自動拋出。
同步指令
Java虛擬機可以支持方法級的同步和方法內部一段指令序列的同步。這兩種同步結構都是使用管理(Monitor)來支持的。
方法級的同步是隱含的,既無需通過字節碼指令來控制,也實現在方法調用和返回操作之中。
同步一段指令序列通常是由Java語言中的synchronize語句塊來表示的,Java虛擬機的指令集中有monitorenter和monitorexit兩條指令來支持synchronize關鍵字的語義,正確實現synchronized關鍵字需要Java編譯器與Java虛擬機兩者共同協作支持
本文永久更新鏈接地址:http://www.linuxidc.com/Linux/2016-04/129844.htm
JVM-類加載機制
獲取C++類成員變量的地址偏移
相關資訊
JVM字節碼 字節碼指令
本文評論
查看全部評論 (0)
表情:
姓名:
匿名
字數
同意評論聲明
評論聲明
尊重網上道德,遵守中華人民共和國的各項有關法律法規
承擔一切因您的行為而直接或間接導致的民事或刑事法律責任
本站管理人員有權保留或刪除其管轄留言中的任意內容
本站有權在網站內轉載或引用您的評論
參與本評論即表明您已經閱讀并接受上述條款
最新資訊
CentOS 6.4下雙網卡bond配置
CentOS6.x雙網卡采用主-備份策略綁定(bond
ORA-30036故障解決方法案例
ORA-03114: 未連接到 ORALCE 解決方法案例
Oracle RAC系統內存無法釋放解決
Oracle Goldengate在HP平臺裸設備文件系統
OGG升級運行ggsic報Unable to find library
Linux vi命令大全
VMware虛擬機主機模式下與主機互ping通
Linux內核中container_of函數詳解
背景:
閱讀新聞
獲取C++類成員變量的地址偏移
[日期:2016-04-05]
來源:Linux社區
作者:openlib
[字體:大 中 小]
今天有在校學生問怎么獲取類中的成員變量的地址偏移量,這個應該是很多初學C++的人很好奇的問題。以前我在學校的時候,也有過這種需求。忘了當時是要寫什么“奇怪的程序”了,反正需要獲取一個類的成員變量的地址偏移量。
其實這個問題很簡單,如果你了解C++的類對象內存分布的話,這個根本不是問題。我給他舉了個例子:
struct A
{
int i;
};
&((A*)0)->i; // 這樣就可以獲取到偏移量了。他表示不理解,OK,我們來具體說說。
假如定義個變量A a; 我們都知道 &a表示變量a的首地址,&(a.i)表示變量i的地址,那么&(a.i)減去&a不就得到i的偏移量了嗎?
是的,就是這么簡單。那么這個例子&((A*)0)->i;有什么關系呢?
&((A*)0)的地地址就是0,所以&((A*)0)->i 等于&((A*)0)->i減去0。
那個學生更好奇了,為什么&((A*)0)->i 不會出問題?這個例子里并沒有為A的對象分配內存,那怎么可以得到它的地址呢?
是的,這里確實沒有分配內存,但是這個例子里我們并沒有要求有內存,我們也不對內存進行操作,所以不會引來崩潰。
&((A*)0)->i只是借助編譯器為我們計算出它的地址。當編譯器要用要一個成員變量的時候,它會根據對象的首地址加上成員的偏移量得到成員變量的地址。當對象的首地址為0時,得到的成員變量地址就是它的偏移量。
到這里,明白了吧!
本文永久更新鏈接地址:http://www.linuxidc.com/Linux/2016-04/129845.htm
JVM-字節碼指令
C語言中結構體的初始化
相關資訊
C++類 C++類成員變量
教你如何用C++創建一個特殊的類 (今 06:23)
C++類中虛表的詳細講解 (10/07/2016 08:15:54)
C++類的實例化對象的大小之sizeof( (02/05/2015 09:03:59)
C++空類實例大小不是0原因 (10/07/2016 08:27:55)
編寫C++類的條款 (04/12/2015 09:43:44)
本文評論
查看全部評論 (0)
表情:
姓名:
匿名
字數
同意評論聲明
評論聲明
尊重網上道德,遵守中華人民共和國的各項有關法律法規
承擔一切因您的行為而直接或間接導致的民事或刑事法律責任
本站管理人員有權保留或刪除其管轄留言中的任意內容
本站有權在網站內轉載或引用您的評論
參與本評論即表明您已經閱讀并接受上述條款
最新資訊
教你如何用C++創建一個特殊的類
Linux下的syslog日志守護進程深入理解
Adobe Creative Cloud本地安全限制繞過漏洞
眾包組織暴力破解比特幣錢包
CentOS 6.6 搭建Zabbix 3.0.3 過程
CentOS 6.5安裝搭建Zabbix3.0詳解PDF
MySQL同實例下復制表的2種方法
MySQL5.6的密碼存放方式基礎知識
C字符串相關知識總結
C malloc和calloc函數總結