代码解析Dex文件

Android源码:http://androidxref.com/6.0.1_r10/xref/frameworks/base/core/java/android/app/ActivityThread.java

Android文档:https://source.android.com/docs/core/runtime/instruction-formats?hl=zh-cn

搜索DexHeader

try、catch、finally三个语句的执行顺序

如果 try 块中没有异常抛出,程序会直接跳过 catch 块,执行 finally 块。
如果 try 块中有异常抛出,并且有匹配的 catch 块处理该异常,先执行匹配的 catch 块,然后执行 finally 块。
如果 try 块中有异常抛出,但没有匹配的 catch 块处理该异常,先执行 finally 块,然后将异常抛出至上层调用栈。

System.arraycopy 方法

//System.arraycopy 是 Java 中用于复制数组内容的方法。它的签名如下:
public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
/*其中:
src:源数组,即要从中复制数据的数组。
srcPos:源数组中开始复制的起始位置索引。
dest:目标数组,即要将数据复制到其中的数组。
destPos:目标数组中开始复制的起始位置索引。
length:要复制的元素数量*/

System.out.printf方法

System.out.printf("%-12s: %s\r\n", "magic", Utils.bytes2HexString(dexType.dexHeader.magic));
printf 方法与 System.out.println 类似,但是它允许使用格式化字符串来定义输出的格式。
"%-12s: %s\r\n"
% 开始表示格式化标志的起始。
- 表示左对齐(在字符串字段内,右对齐是默认的)。
12 表示最小宽度,确保输出的字符串至少占据 12 个字符的宽度。
s 表示后续参数是一个字符串。
: 是一个字面值,即将在输出中显示 : 字符。
%s 是格式化字符串的占位符,用来接收第一个参数 "magic"
\r\n 表示换行符,确保每次输出后换行。
"magic":作为格式化字符串的第一个参数,将填充到 %s 的位置。
Utils.bytes2HexString(dexType.dexHeader.magic):作为格式化字符串的第二个参数,调用 Utils.bytes2HexString 方法将 dexType.dexHeader.magic 转换为十六进制字符串表示。

Utils.java(但是在进行位与操作时,会忽略符号位)

public final class Utils
{
public static byte[] readFile(String fileName)
{
File file = new File(fileName);
FileInputStream fis = null;
ByteArrayOutputStream bos = null;
try
{
fis = new FileInputStream(file);
bot = new ByteArrayOutputStream();
byte[] temp = new byte[1024];
int size = 0;
while((size = fis.read(temp))!=-1)
{
bot.write(temp);
}
return bos.toByteArray();

}catch(Exception e)
{
System.out.println("read file error:"+e.toString);
}finally
{
if(fis != null)
{
try
{
fis.close();
}catch(Exception e)
{
System.out.println("close file error:"+e.toString);
}
try
{
bot.close();
}catch(Exception e)
{
System.out.println("close file error:"+e.toString);
}
}
}
}
public static int byte2Int_4(byte[] res, int pOff)
{
int targets = (res[pOff+0] & 0xff)
|(res[pOff+1] & 0xff00)
|((res[pOff+2] <<24)>>>8)
|(res[pOff+3]<<24);
return targets;
}
static class RETULEB128
{
int retValue;
int readSize;
}
public static RETULEEB128 readULEB128(byte[] data, int pOff)
{
try
{
RETULEB128 ret = new RETULEB128();
int result = 0;
int shift = 0;
int byteRead = 0;
int i = -1;

while(true)
{
i++;
if(pOff+i>=data.length)
{
throw new IOException("pOff+i >=data.length");
}
int currentByte = data[pOff + i];
bytesRead++;
result |=(currentByte & 0x7F)<<shift; // 将当前字节的低7位加入到 result 中,0x7F二进制:0111 1111
shift +=7;

if((currentByte & 0x80) == 0) // 检查当前字节的最高位是否为0,如果为0,则表示这是最后一个字节,0x80二进制:1000 0000
{
break;
}
if(byteRead > 5)
{
throw new IOException("Invalid ULEB128 encoded data: more than 5 bytes");
}
}
ret.retValue = result;
ret.readSize = bytesRead;
return ret;
}catch(IOException ioe)
{
ioe.printStackTrace();
}
return null;
}
}