【问题标题】:Android Verifier failure due to class length?由于类长度导致Android验证器失败?
【发布时间】:2012-04-07 16:32:57
【问题描述】:

我正在编写我的第一个,当然是业余的,android 项目。目前,我正在 viewpager 类中创建按钮,但我达到了在 instantiateItem 内添加代码、任何代码都会导致 viewpager 失败的地步。即使是不做任何事情的代码,例如: int a = 1; 只要它似乎是关键行号,就会导致崩溃。整个程序运行良好,然后我在 instantiateItem 中的任何位置添加一行任何代码,然后它崩溃了。 Android 构建目标是 4.0,min sdk 是 14。模拟器和我的 Galaxy nexus 手机都发生崩溃。 viewpager 内的代码总长度为 1000 行,包括 cmets 和空白,删除后的代码约为 850 行。

确切的错误:

VFY: 0x9c6[1] 处的无效切换目标 26 (-> 0x9e0)

VFY:在 0x9c6 拒绝操作码 0x2b

W/dalvikvm(8886): VFY: 拒绝 Lcharacter/sheet/CharacterViewer$MyPagerAdapter;.instantiateItem (Landroid/view/View;I)Ljava/lang/Object;

W/dalvikvm(8886):验证程序拒绝了 Lcharacter/sheet/CharacterViewer$MyPagerAdapter 类;

W/dalvikvm(8886):threadid=1:线程以未捕获的异常退出(组=0x40a661f8)

E/AndroidRuntime(8886): java.lang.VerifyError: character/sheet/CharacterViewer$MyPagerAdapter

字符查看器活动代码:

public class CharacterViewer extends Activity { 
final DBAdapter db = new DBAdapter(this);   
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.pager);     
    Intent startCharacterViewer = getIntent();
    final int activePagerPage = startCharacterViewer.getIntExtra("activePagerPage", 0);
    MyPagerAdapter adapter = new MyPagerAdapter();
    ViewPager myPager = (ViewPager) findViewById(R.id.myfivepanelpager);
    myPager.setAdapter(adapter);
    myPager.setCurrentItem(activePagerPage); } 

private class MyPagerAdapter extends PagerAdapter {

    Intent startCharacterViewer = getIntent();
    final int activeCharacter = startCharacterViewer.getIntExtra("activeCharacter", 0);
    public int getCount() {
        return 5;          
    }

    public Object instantiateItem(View collection, int position) {
        db.open();
        LayoutInflater inflater = (LayoutInflater) collection.getContext()
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        String name = db.getAttribute(activeCharacter, 1);
        int level = Integer.valueOf(db.getAttribute(activeCharacter, 2));
        //repeats for many variables (106 total)
        db.close();
        View v = null;

        switch (position) {
        //case 0
        case 0:
            v = inflater.inflate(R.layout.details, null); 
            break;
        //case 1
        case 1:
            v = inflater.inflate(R.layout.features, null);
            break;
        //case 2    
        case 2:
            v = inflater.inflate(R.layout.summary, null); 
            TextView text1 = (TextView) v.findViewById(R.id.textViewName);
            text1.setText (name + "    level " + level + " " + characterClass);
            //repeats many times for more text views
            //many many buttons and text views defined here
        //case 3   
        case 3: 
            v = inflater.inflate(R.layout.skills, null);
            //more text views and buttons defined here

        case 4:
            v = inflater.inflate(R.layout.inventory, null);
            break;
        }



        ((ViewPager) collection).addView(v, 0);


        return v;
    }

按钮和文本视图集代码嵌套在 instantiateItem 的 case 区域内。 其中一个按钮的示例:

            TextView hpUpdaterText1 = (TextView) v.findViewById(R.id.textViewHP);
            TextView hpUpdaterText2 = (TextView) v.findViewById(R.id.textViewSurges);
            final int a1 = hpMax;
            final int b1 = hpSurgeMax;
            View.OnClickListener hpModifierListener = new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    final Dialog myDialog = new Dialog(CharacterViewer.this);
                    myDialog.setContentView(R.layout.edithitpoints);
                    myDialog.setTitle("Modify Permanent Health Values");
                    myDialog.setCancelable(true);
                    myDialog.show();                    
                    EditText text1 = (EditText) myDialog.findViewById(R.id.editTextHPMax);
                    text1.setText ("" + (a1));                      
                    EditText text2 = (EditText) myDialog.findViewById(R.id.editTextSurges);
                    text2.setText ("" + (b1));
                    //Cancel button
                    Button button1 = (Button) myDialog.findViewById(R.id.editHitPointsCancel);
                    button1.setOnClickListener(new OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            myDialog.dismiss();
            }});
                    //OK button
                    Button button2 = (Button) myDialog.findViewById(R.id.editHitPointsOK);
                    button2.setOnClickListener(new OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            EditText text1 = (EditText) myDialog.findViewById(R.id.editTextHPMax);
                            String a = text1.getText().toString();
                            if( a.length() == 0 ) {text1.setError( "Value Required" );}
                            EditText text2 = (EditText) myDialog.findViewById(R.id.editTextSurges);
                            String b = text2.getText().toString();
                            if( b.length() == 0 ) {text2.setError( "Value Required" );}
                            if (a.length() != 0 && b.length() != 0){
                            db.open();
                            db.updatePermanentHP(activeCharacter, a, b);                                
                            db.close();
                            //restart activity to update variables
                            Intent startCharacterViewer = new Intent("android.intent.action.SUMMARY");
                            startCharacterViewer.putExtra("activeCharacter", activeCharacter);
                            finish();
                            startCharacterViewer.putExtra("activePagerPage", 2);
                            startActivity(startCharacterViewer);
                            myDialog.dismiss();}
                            else {Toast msg = Toast.makeText(CharacterViewer.this,
                                    "Please enter a value for" + "\n" + "all available fields", Toast.LENGTH_SHORT);
                                    msg.show();;}
            }});
            }};
            hpUpdaterText1.setOnClickListener(hpModifierListener);
            hpUpdaterText2.setOnClickListener(hpModifierListener);

在任何地方添加任何代码行,只要它在 instantiateItem 内都会导致错误。例如,我可以将这段代码剪切并粘贴到 instantiateItem 中的任何位置,这会使程序崩溃。这些变量名不用于任何用途。

示例问题代码块:

        int uuu = 1;
        int aaa = 2;
        int bbb = 3;
        int ccc = 4;
        int ddd = 5;
        int eee = 6;

【问题讨论】:

  • 基于错误“VFY: invalid switch target”,我想知道这个问题是否是欺骗:stackoverflow.com/questions/6025891/…
  • 这里只有 5 个案例,所以可能不是完全相同的问题。该链接确实提到了观看次数的限制,但没有详细说明,我的 googlefu 也没有出现任何问题。无需在案例中添加其他代码即可导致崩溃。

标签: java android


【解决方案1】:

我相当肯定你的问题不是因为课程长度。我见过 8000 行长的旧 J2ME 代码,因为它们将代码全部折叠到一个类中(出于节省空间的原因)。现代手机和 IDE 肯定可以支持更多。发布您的一些代码,也许我们可以提供帮助。

【讨论】:

  • 我添加了更多代码细节,包括一个代码块示例,我可以将其粘贴到 instantiateItem 中的任何位置并导致崩溃
【解决方案2】:

我通过将所有文本视图和按钮代码从 instantiateItem 方法移到它们自己的方法中来解决这个问题,然后为每种情况调用这些方法,而不是将代码直接放在 instantiateItem 中。

【讨论】:

    【解决方案3】:

    带有“正常大小”代码片段(即少于 10000 行)的 dex VRFY 错误消息意味着您遇到了以下任一方面的错误:

    1. Dalvik 字节码验证器。 Froyo Dalvik 字节码验证器中有一个错误,看起来与here 相似。您是否在 Froyo 上进行部署/测试?

    2. Java 编译器中的一个错误。如果 Java 编译器生成不正确的 Java 字节码,那么 Dalvik 字节码也将不正确。如果您使用 Eclipse 或 javac 进行编译,则不太可能发生这种情况。

    3. dexer 中的一个错误。 dexer 将 Java 字节码翻译成 Dalvik 字节码。如果翻译过程中出现错误,则会发出不正确的 Dalvik 字节码。

    【讨论】:

    • 这发生在 android 4.0 和 4.0.3 上 - 在决定采用解决方法之前没有尝试任何更低的版本。
    猜你喜欢
    • 2018-02-25
    • 1970-01-01
    • 2018-04-22
    • 1970-01-01
    • 2011-05-06
    • 2018-01-31
    • 1970-01-01
    • 1970-01-01
    • 2015-03-13
    相关资源
    最近更新 更多