我正在玩弄 smali and baksmali在我编写的一个小型 Hello World Android 应用程序上。我的源代码是:
package com.hello;
import android.app.Activity;
import android.os.Bundle;
public class Main extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
然后被拆解为:
.class public Lcom/hello/Main;
.super Landroid/app/Activity;
.source "Main.java"
# direct methods
.method public constructor <init>()V
.locals 0
.prologue
.line 6
invoke-direct {p0}, Landroid/app/Activity;-><init>()V
return-void
.end method
# virtual methods
.method public onCreate(Landroid/os/Bundle;)V
.locals 1
.parameter "savedInstanceState"
.prologue
.line 10
invoke-super {p0, p1}, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)V
.line 11
const/high16 v0, 0x7f03
invoke-virtual {p0, v0}, Lcom/hello/Main;->setContentView(I)V
.line 12
return-void
.end method
我知道这是某种中间表示,但不确定它是什么。据我所知,必须有一些关于如何理解这种表示的规范,但我无法弄清楚如何搜索它。所以给定一个 apk 文件,有人可以通俗地解释一下 Dalvik opcode specification 是如何实现的吗?用于得出这种表示?我目前的理解是这样的:
有关上述两个步骤的任何信息(也许有一些简单的示例)都将极大地帮助我正确理解概念。
更新 1(在 Chris 回复后发布):
所以基本上,我会执行以下操作来获得 Dalvik 字节码:
然后反汇编程序读取 classes.dex 文件并确定 apk 中存在的所有类。你能提供一些关于如何做到这一点的信息吗?它是否以十六进制模式解析文件并查找 Dalvik 规范,然后适本地解析?还是发生了其他事情?例如,当我在 classes.dex 上使用 hexdump 时,它给了我这样的东西:
64 65 78 0a 30 33 ...
这些现在用于操作码查找吗?
实际上,简而言之,我很想知道所有这些“魔法”是如何完成的。因此,例如,如果我要学习编写这个工具,我应该遵循的高级路线图是什么?
最佳答案
您看到的是 davlik 字节码。 Java 代码由 dx 工具翻译成 Dalvik 字节码。 list 是一个单独的问题,我将在一分钟内讨论。实际上,当您编译 Android 应用程序时,dx 工具使用 256 个 dalvik 操作码将您的 Java 代码转换为字节码(对于标准 JVM 应用程序,javac 将 Java 转换为 Java 字节码的方式相同)。
例如,invoke-super 是指示 dvm(dalvik 虚拟机)调用父类(super class)上的方法的操作码。类似地,invoke-interface 指示 dvm 调用接口(interface)方法。
所以你可以看到
super.onCreate(savedInstanceState);
翻译成
invoke-super {p0, p1}, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)
在这种情况下,invoke-super 有两个参数,{p0,p1 组和 Landroid/app/Activity;->onCreate(Landroid/os/Bundle;) 参数是方法规范,必要时用于查找和解析方法。
然后就是构造函数区的invoke-direct调用
invoke-direct {p0}, Landroid/app/Activity;-><init>()V
每个类都有一个init 方法,用于初始化类的数据成员,也称为构造函数。当你构造一个类时,虚拟机也必须调用父类(super class)的构造函数。这解释了为什么您的类的构造函数调用 Activity 构造函数。
关于 list ,会发生什么(如果您查看源代码,这都在 Dalvik 规范中)是编译器(生成 apk 文件)将 list 转换为更压缩的格式(二进制 xml)为了节省空间。 list 与您发布的代码没有任何关系,它更多地指示 dvm 如何处理应用程序是一个关于 Activities、Services 的整体,等。您发布的是实际执行的内容。
这是对您问题的高级回答。如果您需要更多,请告诉我,我会尽力而为。
编辑 你基本上是对的。反编译器从 dex 文件中读取二进制数据作为字节流。它了解格式应该是什么,并且能够提取常量、类等信息。关于操作码,这正是它所做的。它了解每个操作码的字节值是什么(或者它在 dex 文件中的表示方式)并且能够将其转换为人类可读的字符串。如果你要实现这个,除了了解编译器的一般基础知识外,我将从深入了解 dex 文件的结构开始。从那里,您需要构建一个表,将操作码值与人类可读的字符串相匹配。使用该信息和一些关于字符串常量等的附加信息,您可以构建已编译类的文本文件表示。这有意义吗?
关于java - 了解 Dalvik 代码的反汇编?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4820285/
如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby
在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
我的主要目标是能够完全理解我正在使用的库/gem。我尝试在Github上从头到尾阅读源代码,但这真的很难。我认为更有趣、更温和的踏脚石就是在使用时阅读每个库/gem方法的源代码。例如,我想知道RubyonRails中的redirect_to方法是如何工作的:如何查找redirect_to方法的源代码?我知道在pry中我可以执行类似show-methodmethod的操作,但我如何才能对Rails框架中的方法执行此操作?您对我如何更好地理解Gem及其API有什么建议吗?仅仅阅读源代码似乎真的很难,尤其是对于框架。谢谢! 最佳答案 Ru
我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的
几个月前,我读了一篇关于rubygem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:
我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www
我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur
我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我
什么是ruby的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht