《深入理解Java虛擬機》-(實戰)練習修改class文件

来源:https://www.cnblogs.com/chenscript/archive/2019/08/12/11343270.html
-Advertisement-
Play Games

這是一篇修改class文件的文章。註釋並不完全,要抓住這次練習的目的: boolean在虛擬機中是以何種方式解讀的 好的,開始我的表演 1.安裝asmtools.jar(本文尾部有步驟) 2.編寫一個java文件,並編譯,執行 2.1 Foo.java 1 public class Foo { 2 ...


這是一篇修改class文件的文章。註釋並不完全,要抓住這次練習的目的:

boolean在虛擬機中是以何種方式解讀的

好的,開始我的表演

1.安裝asmtools.jar(本文尾部有步驟)

2.編寫一個java文件,並編譯,執行  2.1 Foo.java
 1 public class Foo {
 2   public static void main(String[] args) {
 3     boolean flag = true;
 4     if (flag)   {
 5         System.out.println("Hello, Java!");
 6     }
 7     if (flag == true) {
 8         System.out.println("Hello, JVM!");
 9     }
10   }
11 }       
View Code

 

2.2 編譯並運行

[root@localhost tmp]# javac Foo.java
[root@localhost tmp]# java Foo
Hello, Java!
Hello, JVM!

 

3.查看編譯後的java文件,class (註意看黃色部分的變化)

[root@localhost tmp]# javap -verbose Foo
Classfile /usr/local/asmtools-7.0-build/binaries/lib/tmp/Foo.class
  Last modified Aug 12, 2019; size 493 bytes
  MD5 checksum d51944604c5b4e45cb895501910347ea
  Compiled from "Foo.java"
public class Foo
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #7.#17         // java/lang/Object."<init>":()V
   #2 = Fieldref           #18.#19        // java/lang/System.out:Ljava/io/PrintStream;
   #3 = String             #20            // Hello, Java!
   #4 = Methodref          #21.#22        // java/io/PrintStream.println:(Ljava/lang/String;)V
   #5 = String             #23            // Hello, JVM!
   #6 = Class              #24            // Foo
   #7 = Class              #25            // java/lang/Object
   #8 = Utf8               <init>
   #9 = Utf8               ()V
  #10 = Utf8               Code
  #11 = Utf8               LineNumberTable
  #12 = Utf8               main
  #13 = Utf8               ([Ljava/lang/String;)V
  #14 = Utf8               StackMapTable
  #15 = Utf8               SourceFile
  #16 = Utf8               Foo.java
  #17 = NameAndType        #8:#9          // "<init>":()V
  #18 = Class              #26            // java/lang/System
  #19 = NameAndType        #27:#28        // out:Ljava/io/PrintStream;
  #20 = Utf8               Hello, Java!
  #21 = Class              #29            // java/io/PrintStream
  #22 = NameAndType        #30:#31        // println:(Ljava/lang/String;)V
  #23 = Utf8               Hello, JVM!
  #24 = Utf8               Foo
  #25 = Utf8               java/lang/Object
  #26 = Utf8               java/lang/System
  #27 = Utf8               out
  #28 = Utf8               Ljava/io/PrintStream;
  #29 = Utf8               java/io/PrintStream
  #30 = Utf8               println
  #31 = Utf8               (Ljava/lang/String;)V
{
  public Foo();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 1: 0


  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=2, args_size=1    
         0: iconst_1                    //常量1入棧
         1: istore_1                    //把棧頂值存儲到局部變數表下標為1的位置,即flag =1;  
         2: iload_1                     //取局部變數表中下標為1的變數壓棧
         3: ifeq          14            //(jump if i == 0) 將棧頂值與0比較,如果相等,則跳入14步驟。
         6: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
         9: ldc           #3                  // String Hello, Java!
        11: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        14: iload_1                     //取局部變數表中下標為1的變數壓棧
        15: iconst_1                    //常量1入棧
        16: if_icmpne     27            //比較棧頂兩個值,如果不相等,則跳轉到27   
        19: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
        22: ldc           #5                  // String Hello, JVM!
        24: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        27: return
      LineNumberTable:
        line 3: 0
        line 4: 2
        line 5: 6
        line 7: 14
        line 8: 19
        line 10: 27
      StackMapTable: number_of_entries = 2
        frame_type = 252 /* append */
          offset_delta = 14
          locals = [ int ]
        frame_type = 12 /* same */
}
SourceFile: "Foo.java"
View Code

 

4.使用asmtools.jar修改class文件

[root@localhost tmp]# java -jar ../asmtools.jar jdis Foo.class > Foo.jasm.1
[root@localhost tmp]# ls
Foo.class  Foo.jasm.1  Foo.java
[root@localhost tmp]# java -cp ../asmtools.jar org.openjdk.asmtools.jdis.Main Foo.class > Foo.jasm.1
[root@localhost tmp]# awk 'NR==1,/iconst_1/{sub(/iconst_1/,"iconst_2")} 1' Foo.jasm.1 > Foo.jasm
[root@localhost tmp]# ls
Foo.class  Foo.jasm  Foo.jasm.1  Foo.java
[root@localhost tmp]# java Foo
Hello, Java!
Hello, JVM!

 

5.再次編譯,執行

[root@localhost tmp]# java -jar  ../asmtools.jar jasm Foo.jasm
[root@localhost tmp]# java Foo
Hello, Java!
[root@localhost tmp]# ls
Foo.class  Foo.jasm  Foo.jasm.1  Foo.java

 

6.查看修改後的class文件

[root@localhost tmp]# javap -verbose Foo
Classfile /usr/local/asmtools-7.0-build/binaries/lib/tmp/Foo.class
  Last modified Aug 12, 2019; size 431 bytes
  MD5 checksum 18cfb8b8b7d9d49e9ffce213e70c8898
  Compiled from "Foo.jasm"
public class Foo
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = String             #10            // Hello, Java!
   #2 = String             #11            // Hello, JVM!
   #3 = Fieldref           #27.#12        // java/lang/System.out:Ljava/io/PrintStream;
   #4 = Methodref          #8.#17         // java/lang/Object."<init>":()V
   #5 = Methodref          #13.#30        // java/io/PrintStream.println:(Ljava/lang/String;)V
   #6 = Utf8               (Ljava/lang/String;)V
   #7 = Utf8               out
   #8 = Class              #9             // java/lang/Object
   #9 = Utf8               java/lang/Object
  #10 = Utf8               Hello, Java!
  #11 = Utf8               Hello, JVM!
  #12 = NameAndType        #7:#23         // out:Ljava/io/PrintStream;
  #13 = Class              #15            // java/io/PrintStream
  #14 = Utf8               ([Ljava/lang/String;)V
  #15 = Utf8               java/io/PrintStream
  #16 = Utf8               main
  #17 = NameAndType        #29:#20        // "<init>":()V
  #18 = Utf8               SourceFile
  #19 = Utf8               println
  #20 = Utf8               ()V
  #21 = Utf8               StackMapTable
  #22 = Utf8               Foo.jasm
  #23 = Utf8               Ljava/io/PrintStream;
  #24 = Utf8               Code
  #25 = Class              #26            // Foo
  #26 = Utf8               Foo
  #27 = Class              #28            // java/lang/System
  #28 = Utf8               java/lang/System
  #29 = Utf8               <init>
  #30 = NameAndType        #19:#6         // println:(Ljava/lang/String;)V
{
  public Foo();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #4                  // Method java/lang/Object."<init>":()V
         4: return


  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=2, args_size=1
         0: iconst_2                     //載入常量2入棧
         1: istore_1                     //把棧頂值存儲到局部變數表下標為1的位置,即flag =2;
         2: iload_1                        //取局部變數表中下標為1的變數壓棧
         3: ifeq          14
         6: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
         9: ldc           #1                  // String Hello, Java!
        11: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        14: iload_1                    //取局部變數表中下標為1的變數壓棧
        15: iconst_1                   //常量1入棧
        16: if_icmpne     27           //比較棧頂兩個值,如果不相等,則跳轉到27
        19: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
        22: ldc           #2                  // String Hello, JVM!
        24: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        27: return
      StackMapTable: number_of_entries = 2
        frame_type = 252 /* append */
          offset_delta = 14
          locals = [ int ]
        frame_type = 12 /* same */
}
SourceFile: "Foo.jasm"

  

 

附:asmtools.jar的安裝(centos 6/7)

0.先cd進入需要安裝到的目錄地址  1. Mercurial是一種輕量級分散式版本控制系統,採用Python語言實現。
yum install hg

2. 版本是2.6.2,發現不是最新版,去官方下載centos 7最新版3.9.2

wget https://www.mercurial-scm.org/release/centos7/RPMS/x86_64/mercurial-3.9.2-1.x86_64.rpm

3.升級2.6.2 到3.9.2 (centos 6 我就沒有用這一步。。)

rpm -Uvh mercurial-3.9.2-1.x86_64.rpm

4.安裝ASMTOOLS.jar

hg clone http://hg.openjdk.java.net/code-tools/asmtools/ asmtools
cd asmtools/build/
yum install ant
ant //編譯生成asmtools.jar

5.生成的jar位置:

[root@localhost lib]# ls
asmtools.jar
[root@localhost lib]# pwd
/usr/local/asmtools-7.0-build/binaries/lib

  

  

  

  

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Problem Description Problem Description Euler is a well-known matematician, and, among many other things, he discovered that the formulan^{2} + n + 41 ...
  • 一、多線程 1.我們的環境 (1)xubuntu 16.04(2)anaconda(3)pycharm(4)python 3.6 2.程式:一堆代碼以文本的形式存入一個文檔 3.進程:程式運行的一個狀態。 特點:(1)其中包含地址控制項、記憶體、數據棧等;(2)每個進程由自己完全獨立的運行環境,多進程共 ...
  • Windows下Beyond Compare 4 30天評估到期了的話,可以嘗試下麵兩種方式: 破解方式把Beyond Compare 4安裝文件夾下麵的BCUnrar.dll文件刪掉就行了,但是這種依然會提示在試用期 BC4註冊碼:可以用下麵這個註冊碼,有效期是到2019年12月 BEGIN LI ...
  • 使用dir()我們可以知道這個數據類型的內置函數有什麼方法: 1.迭代器 iterable:可迭代的 迭代就是將數據能夠一個一個按順序取出來 上面數據類型返回為真說明它是可以迭代的,反之是不可迭代的 可迭代協議: 就是內部要有一個__iter__()來滿足要求 當一個具有可迭代的數據執行__iter ...
  • 通過DefaultMQPullConsumer作為預設實現,這裡的啟動過程和Producer很相似,但相比複雜一些 【RocketMQ中Producer的啟動源碼分析】 DefaultMQPullConsumer的構造方法: 這裡會封裝一個DefaultMQPullConsumerImpl,類似於P ...
  • 1.爬取豆瓣top250書籍 結果 2.把評分為9.0的書籍保存到book_out.csv文件中 ...
  • 零基礎學python,python視頻教程 這是我收集到的互聯網上的視頻資源,所有內容均來自互聯網。僅供學習使用。 目前我在也在學習過程中,會把學習過程中遇到問題以及解決問題的方式,總結到我的公眾號【趣學程式】裡面。 偶爾會發表幾篇文章,供給大家學習使用。茫茫人海之中,只為交個朋友。還請多多多指教小 ...
  • 最近整理ssm,寫完demo案例,無論如何都訪問不了後臺,百度了好多,終於解決了問題所在 先看頁面信息: 因為一直報404錯誤,一直找路徑是不是弄錯了,或配置文件弄錯了,僅僅這個配置文件都看了無數遍,然而並沒有發現問題,後來百度這個描述才發現了問題The origin server did not ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...