我是靠谱客的博主 安详眼睛,这篇文章主要介绍android找不到方法(unable to resolve virtual method)的警告与分析,现在分享给大家,希望可以做个参考。

今天同事问我这里怎么会提示这个

复制代码
1
2
3
W/dalvikvm: VFY: unable to resolve virtual method 1886: Landroid/preference/PreferenceFragment;.onAttach (Landroid/content/ContextV D/dalvikvm: VFY: replacing opcode 0x6f at 0x0000

环境

是这样出现的
minSdkVersion 14
targetSdkVersion 27

复制代码
1
2
3
FragmentTransaction transaction = getFragmentManager().beginTransaction(); transaction.replace(R.id.setting_frame,new SettingWelcomeFragment()); transaction.commit();

SettingWelcomeFragment中

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class SettingWelcomeFragmentextends Fragment { protected boolean onKeyDown(int keyCode,KeyEvent event){ return false; } @Override public void onAttach(Activity activity){ super.onAttach(activity); Log.e("activity","onAttach"); } @Override public void onAttach(Context context){ Log.e("context","onAttach"); super.onAttach(context); } }

在api19的手机上会出现这个提示。

原因

1,onAttach(Context context)是API27新加的方法,在API14的手机上是没有这个方法的。
2,打印log的时候,可以看到android4.4的机器上没有打印出context的log(就是完全没被调用到。)
3,但是还是会提示,是因为加载class的时候,检查到有super.onAttach(context) 的方法,art试图建索引,但是没建成功,所以提示报错。

这个提示在哪里打印的

这个代码是在art中打印出来的,所以打印的时间点是在加载类的时候(即ClassLoader),所以这个提示只会出现一次.在加载类的时候,没找到方法的时候。提示
第一行提示是说找不到,第二行提示是把这个找不到的方法替换成空方法。

这个比较好找,因为源码中只有一个地方的前缀是VFY

method_verifier

复制代码
1
2
3
4
std::ostream& MethodVerifier::LogVerifyInfo() { return info_messages_ << "VFY: " << PrettyMethod(dex_method_idx_, *dex_file_) << '[' << reinterpret_cast<void*>(work_insn_idx_) << "] : "; }

dex_to_dex_compiler

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void DexCompiler::CompileReturnVoid(Instruction* inst, uint32_t dex_pc) { DCHECK_EQ(inst->Opcode(), Instruction::RETURN_VOID); if (unit_.IsConstructor()) { // Are we compiling a non clinit constructor which needs a barrier ? if (!unit_.IsStatic() && driver_.RequiresConstructorBarrier(Thread::Current(), unit_.GetDexFile(), unit_.GetClassDefIndex())) { return; } } // Replace RETURN_VOID by RETURN_VOID_NO_BARRIER. VLOG(compiler) << "Replacing " << Instruction::Name(inst->Opcode()) << " by " << Instruction::Name(Instruction::RETURN_VOID_NO_BARRIER) << " at dex pc " << StringPrintf("0x%x", dex_pc) << " in method " << PrettyMethod(unit_.GetDexMethodIndex(), GetDexFile(), true); inst->SetOpcode(Instruction::RETURN_VOID_NO_BARRIER); }

为什么编译没报错呢,因为编译的时候有这个方法,但是实际跑的时候,手机上的库和编译时候的库有出入,所以art在这里做了简单的兼容/提示处理。

避免这个问题可以这样做:

解决方法一

把targetsdk修改成19,编译过程中as会提示错误的,最大程度的避免这个奇奇怪怪的错误

解决方法二

用SupportV4的方法getSupportFragmentManager,不用系统上的getFragmentManager的方法,SupportV4本身做了不少兼容处理,所以也不会有警告,也能被调用到。

最后

以上就是安详眼睛最近收集整理的关于android找不到方法(unable to resolve virtual method)的警告与分析的全部内容,更多相关android找不到方法(unable内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(84)

评论列表共有 0 条评论

立即
投稿
返回
顶部