使用ASM來書寫Java程式碼-2
1. 類:
a) 陣列:
i. 建立:
mv.visitInsn(ICONST_3);
mv.visitIntInsn(NEWARRAY, T_INT);
mv.visitVarInsn(ASTORE, 1); // 將陣列引用存到區域性變數棧1號的位置
等價於:
int[] a = new int[3];
ii. 取值:
mv.visitVarInsn(ALOAD, 1); // 陣列引用在區域性變數棧1號的位置
mv.visitInsn(ICONST_1);
mv.visitInsn(IALOAD);
mv.visitVarInsn(ISTORE, 2);
等價於:
int b = a[1];
iii. 賦值:
mv.visitVarInsn(ALOAD, 1);
mv.visitInsn(ICONST_1);
mv.visitInsn(ICONST_2);
mv.visitInsn(IASTORE);
等價於:
a[1] = 2;
b) 建構函式:
i. <init>:
1. 建立:
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", ()V");
mv.visitInsn(RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
說明:建構函式<init>在執行時,需要首先執行父類的建構函式或者類內部其他構造
函式。
2. 呼叫:
mv.visitTypeInsn(NEW, "asm/A");
mv.visitInsn(DUP);
mv.visitMethodInsn(INVOKESPECIAL, "asm/A", "<init>", "()V");
mv.visitVarInsn(ASTORE, 1);
等價於:
A a = new A();
說明:在初始化一般物件時,我們需要先呼叫NEW指令,來建立該物件例項。而由於
後續的INVOKESPECIAL指令是呼叫類的建構函式,而該指令執行完以後,對物件的引
用將從棧中彈出,所以在NEW指令執行完以後,INVOKESPECIAL指令執行以前,我們
需要呼叫DUP指令,來增加物件引用的副本。
ii. <clinit>:
1. 建立:
MethodVisitor mv = cw.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null);
mv.visitCode();
mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
"Ljava/io/PrintStream;");
mv.visitLdcInsn("hello world");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println",
"(Ljava/lang/String;)V");
mv.visitInsn(RETURN);
mv.visitMaxs(2, 0);
mv.visitEnd();
等價於:
static {
System.out.println("hello world");
}
2. 呼叫:<clinit>在類被載入時自動呼叫。
c) 欄位:
i. 一般欄位:
1. 建立:
FieldVisitor fv = cw.visitField(ACC_PRIVATE, "a", "I", null, null);
fv.visitEnd();
等價於:
private int a;
2. 讀取:讀取類當中名字為a,型別為int的欄位的值。
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, "asm/A", "a", "I");
3. 設定:
mv.visitVarInsn(ALOAD, 0);
mv.visitInsn(ICONST_2);
mv.visitFieldInsn(PUTFIELD, "asm/A", "a", "I");
等價於:
a = 2;
ii. 靜態欄位:
1. 建立:
FieldVisitor fv = cw.visitField(ACC_PRIVATE + ACC_STATIC, "a", "I", null,
null);
fv.visitEnd();
等價於:
private static int a;
2. 讀取:
mv.visitFieldInsn(GETSTATIC, "asm/A", "a", "I");
3. 設定:
mv.visitInsn(ICONST_2);
mv.visitFieldInsn(PUTSTATIC, "asm/A", "a", "I");
等價於:
a = 2;
d) 方法:
i. 介面方法:
1. 定義:
mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "getA", "()V", null, null);
mv.visitEnd();
2. 呼叫:
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEINTERFACE, "asm/IA", "getA", "()V");
等價於:
public interface IA{
public void geA();
}
public class A implements IA{
public void geA(){…}
}
IA a = new A();
a.getA();
ii. 一般方法:
1. 定義:
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "getA", "()V", null, null);
mv.visitCode();
mv.visitInsn(RETURN);
mv.visitMaxs(0, 1);
mv.visitEnd();
等價於:
public void getA() {}
2. 呼叫:
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEVIRTUAL, "asm/A", "getA", "()V");
等價於:
A a = new A():
a.getA();
iii. 靜態方法:
1. 定義:
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "getA", "()V",
null, null);
mv.visitCode();
mv.visitInsn(RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
等價於:
public static void getA() {}
2. 呼叫:
mv.visitMethodInsn(INVOKESTATIC, "asm/A", "getB", "()V");
等價於:
A.getB();
iv. 說明:一般方法比靜態方法在宣告和呼叫時均要多傳入一個this引用作為引數。另外,當使用INVOKESPECIAL來呼叫方法時,虛擬機器將直接根據指令當中所指明的類型別來呼叫方法;而當使用INVOKEVIRTUAL來呼叫方法時,虛擬機器將根據例項的實際型別來呼叫方法。
e) 異常處理:
i. 宣告:
mv.visitTryCatchBlock(l0, l1, l1, "java/lang/Exception");
mv.visitLabel(l0);
mv.visitLabel(l1);
…
等價於:
try {
…
} catch (Exception e) {
…
}
說明:在visitTryCatchBlock()當中,第一,二,三個引數均是Label例項,其中一,二表示try塊的範圍,三則是catch塊的開始位置。而第四個引數則是異常型別。而當異常發生時,JVM將會將異常例項置於執行棧的
轉載:http://blog.sina.com.cn/s/blog_4b38e200010008tp.html
相關推薦
使用ASM來書寫Java程式碼-2
1. 類: a) 陣列: i. 建立: mv.visitInsn(ICONST_3); mv.visitIntInsn(NEWARRAY, T_INT); mv.visitVarIns
90% 的 Java 程式設計師都說不上來的為何 Java 程式碼越執行越快(2)- TLAB預熱
經常聽到 Java 效能不如 C/C++ 的言論,也經常聽說 Java 程式需要預熱,**那麼其中主要原因是啥呢**? 面試的時候談到 JVM,也有很多面試官喜歡問,**為啥 Java 程式越執行越快呢**? 一般人都能回答上來,類載入,快取預熱等等,但是深入下去,**最重要的卻沒有答上來**,今天本系列
CCF認證201803-2 碰撞的小球 java程式碼實現。
問題描述 數軸上有一條長度為L(L為偶數)的線段,左端點在原點,右端點在座標L處。有n個不計體積的小球線上段上,開始時所有的小球都處在偶數座標上,速度方向向右,速度大小為1單位長度每秒。 當小球到達線段的端點(左端點或右端點)的時候,會立即向相反的方向移動,速度大小仍然為原來大小。 當兩個小
所謂的網頁爬蟲用java程式碼來實現,此程式碼適合在maven專案中使用中使用,因為,程式碼中的類所對應的依賴可以讓maven下載。
//獲得httpClient物件 CloseableHttpClient httpClient = HttpClients.createDefault(); //url公司域名隨便 String url = "https://www.baidu.co
資料結構2--線性表(java程式碼實現線性表的鏈式儲存)
1.鏈式儲存 2.分析 每個節點為一個物件,該物件包含資料域和指標域 整條單鏈表為一個物件,他和節點物件進行組合。 3.
Java筆試題——2的100次方,不用大資料類(Biginteger)來解答
Java筆試題——2的100次方,不用大資料類(Biginteger)來解答 package cn.hncu.offer; public class Two100 { public static void main(String[] args) { int a[]=new int[1];//
開發者筆記3 | Java 程式碼規約第 2 條
返回規約清單列表 規約型別:程式設計規約 - 命名風格 規約級別:強制 規約描述:程式碼中的命名嚴禁使用拼音與英文混合的方式,更不允許直接使用中文的方式 說明: 正確的英文拼寫和語法可以讓閱讀者易於理解,避免歧義。注意,即使純拼音命名方式,也要避免採用。 正例: alibab
開發者筆記2 | Java 程式碼規約第1條
返回規約清單列表 規約型別:程式設計規約 - 命名風格 規約級別:強制 規約描述:程式碼中的命名均不能以下劃線或美元符號開始,也不能以下劃線或美元符號結束 反例: \_name / \_\_name / $name / name_ / name$ / name__
zookeeper - 通過java程式碼連線zookeeper(2)
首先建立一個Maven專案 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www
Java 7: 全面教程-1.2 Java程式碼規格
1.2 Java程式碼規格 寫正確的可執行的Java程式固然重要,但是寫出的程式碼方便閱讀和維護也是相當重要的。普遍相信一個軟體80%的時間都花在維護上。而且,程式設計師的變動率非常的高,所以很有可能是別人在維護你的程式碼。如果你留下的程式原始碼是清楚且簡單易懂的,不管是誰都會非常感謝你。 讓
Java程式碼中如何通過 http來上傳檔案
例子程式碼如下 package example.filetransfer; import java.io.*; import java.net.*; import java.util.*; public class HttpRequestUtil { /** * 傳送ge
Android逆向-java程式碼基礎(2)
0x00 前言 由於是對java語言的複習,所以進度會很快,而且會以smali為主,java只是順便提一下,如果對java有興趣詳細研究的,可以下載pdf仔細的看。 這篇主要涉及到基本資料型別,int,float,char,以及運算。 連結:ht
MongoDB-JAVA-Driver 3.2版本常用程式碼全整理(3)
MongoDB的3.x版本Java驅動相對2.x做了全新的設計,類庫和使用方法上有很大區別。例如用Document替換BasicDBObject、通過Builders類構建Bson替代直接輸入$命令等,本文整理了基於3.2版本的常用增刪改查操作的使用方法。為了避免冗長的篇幅
(2)Hadoop核心 -- java程式碼對MapReduce的例子1
案例一:wordcount字數統計功能 1.1 先準備兩個txt檔案,並上傳到hdfs上 test1.txt hello zhangsan lisi nihao hai zhangsan nihao lisi x xiaoming test2.txt zha
(2)Hadoop核心-java程式碼對MapReduce的操作
上一篇檔案介紹了java程式碼怎麼操作hdfs檔案的,hdfs理念“就是一切皆檔案”,我們現在搞定了怎麼使用java上傳下載等操作了接下來就要處理檔案了,hadoop的mapreduce模組。 一、Hadoop Map/Reduce框架
使用java程式碼來實現dvd管理系統
import java.util.Scanner; /* * DVD管理系統 * 陣列的長度是固定的,當在記憶體中開闢了空間後 * 長度都不能變,後面學習到集合框架的時候,長度是可變化的。 */ public class D
使用java程式碼來列印楊輝三角形圖案
package yanghuisanjiaoxing; import java.util.Scanner; /* * 使用二維陣列列印楊輝三角形的圖案 * * 1 * 1 2 1
Java連線MQ報錯,通道協商失敗 MQJE001: 完成程式碼為“2”,原因為“2059
我也曾經遇到過這個錯誤,當時佇列管理器,佇列,通道都一一建立,但就是報錯 HostName=192.168.8.46 Channel=CH1 QManager=WNMS3_QM MQJE001:
【死磕JVM】——-2、Java程式碼編譯和執行的整個過程
Java程式碼編譯是由Java原始碼編譯器來完成的,流程圖如下: Java位元組碼的執行是由JVM執行引擎來完成的,流程圖如下: Java程式碼編譯和執行的整個過程包含以下三個重要機制: 1.Java程式碼編譯機制。 2.類載入機制。 3.類執行機制。 Java原始碼編
java程式碼書寫規範
一、目的 對於程式碼,首要要求是它必須正確,能夠按照程式設計師的真實思想去執行;第二個的要求是程式碼必須清晰易懂,使別的程式設計師能夠容易理解程式碼所進行的實際工作。在軟體工程領域,源程式的風格統一標誌著可維護性、可讀性,是軟體專案的一個重要組成部分。而目前還沒有成文