Java逆向基礎之靜態變數存取
注意:靜態變數static可以多次賦值,不能多次賦值的是final static
線性同餘偽隨機數演算法LCG 演算法數學上基於公式:
X(n+1) = (a * X(n) + c) % m
其中,各系數為:
模m, m > 0
係數a, 0
增量c, 0
原始值(種子) 0
其中引數c, m, a比較敏感,或者說直接影響了偽隨機數產生的質量。
一般而言,高LCG的m是2的指數次冪(一般2^32或者2^64),因為這樣取模操作截斷最右的32或64位就可以了。多數編譯器的庫中使用了該理論實現其偽隨機數發生器rand()。
這裡m取2^32,a取1664525,c取1013904223
LCG演算法實現例子
public class LCG{public static int rand_state;public void my_srand (int init){rand_state=init;}public static int RNG_a=1664525;public static int RNG_c=1013904223;public int my_rand (){rand_state=rand_state*RNG_a;rand_state=rand_state+RNG_c;return rand_state & 0x7fff;}}
編譯
javac LCG.java
反編譯
javap -c -verbose LCG.class
靜態塊的初始化
static {};descriptor: ()Vflags: ACC_STATICCode:stack=1, locals=0, args_size=00: ldc #5 // int 16645252: putstatic #3 // Field RNG_a:I5: ldc #6 // int 10139042237: putstatic #4 // Field RNG_c:I10: return
ldc #5 取常量1664525壓棧
putstatic #3 從棧頂取值,存入靜態變數RNG_a:I中
ldc #6 取常量1013904223壓棧
putstatic #4 從棧頂取值,存入靜態變數RNG_c:I中
這裡putstatic實現了給靜態變數初始化值。
下面的my_srand()函式將輸入值儲存到rand_state中
public void my_srand(int);descriptor: (I)Vflags: ACC_PUBLICCode:stack=1, locals=2, args_size=20: iload_11: putstatic #2 // Field rand_state:I4: return
iload_1 //將第一個引數(init)壓入棧,為什麼不是iload_0?iload_0已經在預設生成的構造方法中使用了
(iload_0在構造方法中將this壓入棧頂)
putstatic #2 //取出棧頂的init的值,將值儲存至靜態變數rand_state:I
這裡補充說明一下,不知道是譯者還是原作者的問題,這個存的值應該是類的初始化的時候的stack分的靜態變數儲存區域,不是所說的第二儲存位
再看my_rand()
public int my_rand();descriptor: ()Iflags: ACC_PUBLICCode:stack=2, locals=1, args_size=10: getstatic #2 // Field rand_state:I3: getstatic #3 // Field RNG_a:I6: imul7: putstatic #2 // Field rand_state:I10: getstatic #2 // Field rand_state:I13: getstatic #4 // Field RNG_c:I16: iadd17: putstatic #2 // Field rand_state:I20: getstatic #2 // Field rand_state:I23: sipush 3276726: iand27: ireturn
原文評論了17的putstatic #2和20的getstatic #2效率不高,實際上這只是java語句的翻譯而已
試試把
public int my_rand (){rand_state=rand_state*RNG_a;rand_state=rand_state+RNG_c;return rand_state & 0x7fff;}
改成
public int my_rand (){rand_state=rand_state*RNG_a+RNG_c;return rand_state & 0x7fff;}
再看這部分的反編譯
public int my_rand(); descriptor: ()I flags: ACC_PUBLIC Code: stack=2, locals=1, args_size=1 0: getstatic #2 // Field rand_state:I 3: getstatic #3 // Field RNG_a:I 6: imul 7: getstatic #4 // Field RNG_c:I 10: iadd 11: putstatic #2 // Field rand_state:I 14: getstatic #2 // Field rand_state:I 17: sipush 32767 20: iand 21: ireturn
這樣就把原來的20行去掉了,這個應該在原始碼方面最佳化的就別交給JVM去最佳化了,JVM過度最佳化又說與原始碼不符還不好弄
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/3407/viewspace-2813364/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- [java基礎]之變數Java變數
- Java自學入門之靜態變數Java變數
- 靜態變數和非靜態變數變數
- Java靜態變數塊使用案例Java變數
- Java靜態變數在靜態方法內部無法改變值Java變數
- 靜態變數變數
- 靜態變數與靜態方法變數
- java執行緒安全問題之靜態變數、例項變數、區域性變數Java執行緒變數
- Java基礎系列-靜態代理和動態代理Java
- java優化程式設計-靜態變數Java優化程式設計變數
- 【C++】靜態持續變數?如何建立靜態持續變數?C++變數
- 逆向基礎(十三) JAVA (一)Java
- java基礎變數的交換Java變數
- 靜態持續變數變數
- 靜態變數和Session變數Session
- java靜態變數和靜態函式是否可以被繼承,重寫!Java變數函式繼承
- Java基礎-基礎語法-變數與常量Java變數
- C語言區域性變數、全域性變數、靜態區域性變數、靜態全域性變數C語言變數
- 區域性變數和全域性變數(靜態和非靜態)區別變數
- JAVA基礎04——變數與常量Java變數
- static靜態變數的理解變數
- js中的靜態變數JS變數
- 大資料之JAVA基礎(一):資料和變數大資料Java變數
- java基礎的學習之引數的變化使用Java
- 靜態全域性變數和全域性變數變數
- 靜態變數和例項變數區別?變數
- PHP類的靜態(static)方法和靜態(static)變數PHP變數
- Java代理之靜態代理Java
- Java基礎06:變數、常量、作用域Java變數
- 全域性變數和靜態變數的區別變數
- JAVA基礎之八-方法變數作用域和編譯器Java變數編譯
- Java初始化靜態變數的時間順序Java變數
- Linux基礎之Shell與變數Linux變數
- 函式的靜態變數 static函式變數
- C/C++ 靜態變數解析C++變數
- PHP的靜態變數介紹PHP變數
- VBA靜態變數與常量(轉)變數
- 羽夏逆向——逆向基礎