当前位置: 首页 > 知识库问答 >
问题:

这张卡到底有多少内存?(EEPROM和对象删除游戏!)

韩弘壮
2023-03-14

我写了一个简单的程序来检查请求对象删除()方法的功能和我的卡的可用内存。

我的小程序响应以下五种不同类型的APDU命令:

  1. 选择APDU命令:响应:0X9000

为了返回可用内存,我编写了一个方法,该方法使用无限while循环创建大量包含100元素的字节数组,并同时增加计数器。捕获内存不足异常时,该方法返回计数器*100(即调用此方法前的可用内存)

好的,这是程序:

public class ObjDeletion extends Applet {
    public static short counter = 0x0000;

    private ObjDeletion() {
    }

    public static void install(byte bArray[], short bOffset, byte bLength)
            throws ISOException {
        new ObjDeletion().register();
    }

    public void process(APDU arg0) throws ISOException {

        if (selectingApplet()) {
            return;
        }

        byte[] buffer = arg0.getBuffer();

        switch (buffer[ISO7816.OFFSET_INS]) {
        case 0x00:
            counter=0;
            ReturnAvailableMem();
            break;

        case 0x01:
            genLocalArray();
            break;

        case 0x02:
            JCSystem.requestObjectDeletion();
            break;

        default:
            return;

        }

    }

    public void genLocalArray() {
        byte[] LocalArray = new byte[2000];
    }

    public void ReturnAvailableMem() {
        try {
            while (true) {
                byte[] dump = new byte[100];
                counter += 1;
            }

        } catch (Exception e) {

            ISOException.throwIt((short) (counter * 100));
        }
    }
}

现在,有一个问题。这是我向卡发送一些APDU命令时OpenSC工具的输出:

OSC: opensc-tool.exe -s 00a404000b0102030405060708090000 -s 00000000 -s 00020000
 -s 00000000 -s 00020000 -s 00010000 -s 00000000 -s 00020000 -s 00000000 -s 0002
0000 -s 00010000 -s 00020000 -s 00000000

Using reader with a card: ACS CCID USB Reader 0
Sending: 00 A4 04 00 0B 01 02 03 04 05 06 07 08 09 00 00
Received (SW1=0x90, SW2=0x00)

//0::returnAvailableMem()
Sending: 00 00 00 00 
Received (SW1=0xE3, SW2=0x58)

//1::returnAvailableMem()
Sending: 00 00 00 00 
Received (SW1=0x00, SW2=0x00)

//2::requestObjectDeletion()
Sending: 00 02 00 00
Received (SW1=0x90, SW2=0x00)

//3::returnAvailableMem()
Sending: 00 00 00 00
Received (SW1=0xE3, SW2=0x58)

//4::requestObjectDeletion()
Sending: 00 02 00 00
Received (SW1=0x90, SW2=0x00)

//5::genLocalArray()
Sending: 00 01 00 00
Received (SW1=0x90, SW2=0x00)

//6::returnAvailableMem()
Sending: 00 00 00 00
Received (SW1=0xDD, SW2=0x18)

//7::requestObjectDeletion()
Sending: 00 02 00 00
Received (SW1=0x90, SW2=0x00)

//8::returnAvailableMem()
Sending: 00 00 00 00
Received (SW1=0xE3, SW2=0x58)

//9::requestObjectDeletion()
Sending: 00 02 00 00
Received (SW1=0x90, SW2=0x00)

//10::genLocalArray()
Sending: 00 01 00 00
Received (SW1=0x90, SW2=0x00)

//11::requestObjectDeletion()
Sending: 00 02 00 00
Received (SW1=0x90, SW2=0x00)

//12::returnAvailableMem()
Sending: 00 00 00 00
Received (SW1=0xE3, SW2=0x58)

命令0返回0xE358(=58200)。因此,调用此方法之前的内存是58200字节。

命令1返回0x0000,这意味着现在可用内存小于100字节。

命令2返回0x9000,因此成功调用了RequestObjectDelete。

命令3再次返回0xE358,这意味着requestObjectDeletion运行成功。

命令4返回0x9000,因此成功调用了RequestObjectDelete。

命令5返回0x9000,因此现在创建一个包含2000元素的字节数组。

现在我希望该卡的可用内存等于0xE358-2000=0xDB88

但在下一个命令中:

命令6返回0xDD18!i、 我们的卡中有0xDD18 2000=0xE4E8字节的内存空间!

这可能是谁?为什么卡在第一个命令中看不到这400字节(0xE4E8-0xE358)?


共有1个答案

侯令雪
2023-03-14

答案很简单,因为每个数组(以及其他对象)都需要“头”来指示其类型、大小等。为此,您需要仔细阅读JCRE和JCVM规范。

我没有检查“header”的精确大小,但您可以将其想象为(100'header')*X,而不是普通的100*X

这也解释了优化技巧:创建一个大数组比使用许多小数组节省更多内存——但是当然也有权衡,比如代码变得不那么可读。

 类似资料:
  • 问题内容: 具有100个属性的一个对象所消耗的存储空间是否与每个具有一个属性的100个对象所消耗的存储空间相同? 为一个对象分配多少内存? 添加属性时会使用多少额外空间? 问题答案: 指出,这不是一个容易回答的简单问题: JVM可以自由地以内部或大端或小端的任何方式存储数据,并具有一定的填充或开销,尽管基元必须表现得好像它们具有官方大小一样。 例如,JVM或本机编译器可能会决定将64位长块(如)存

  • 问题内容: 我需要存储大量的日期(可能足够大,以至于需要考虑使用的堆空间量,因此请不要讲授过早的优化),我想知道使用某种原始表示是否有意义java.util.Date(或其他一些现有的Date类)的形式。我知道我可以进行一些性能分析来尝试一下,但是有人知道一个Date对象使用多少字节的内存吗? 问题答案: 我的直觉反应是Date的内存开销非常小。检查源代码,似乎该类仅包含一个实例字段(长为毫秒)。

  • 问题内容: 让我们开始吧,我有一个’handler’类,里面充满了getters和setters,并且其中包括添加和删除对象的代码,它看起来像这样: 请注意,“ GameObject”是一个类,所有对象都对该类进行扩展, 然后在此处创建一个对象, 内部参数是我要添加的对象的参数。当然,每个对象都是其自己的类。现在我想删除对象F1Jutsu(如果它的x值在游戏外部),并且该对象每秒向右移动一次(这样

  • 我有以下型号: 当我运行下面的查询时,用户模型也被删除 有没有办法在不删除用户的情况下删除问题? 我试着重复这些问题但没有用 我认为查询集是懒惰的,所以也许我需要在删除之前评估它,所以我打印了它,但这不起作用。 我知道,将ForeignKey设置为null将为我提供诸如clear和remove之类的方法,但我不想这样做,因为我不希望出现任何孤立的用户问题。 我更新了ForeignKey,如下所示

  • 我有一个模型,在几个模型中设置为外键。现在从模型中删除任何对象时,如果该对象在这些模型中被引用,则会抛出ProtectedError。我想让用户在一次操作中删除包含所有受保护对象的对象。 我只需调用 但是当有自己的受保护对象时,操作失败并抛出另一层。我想要实现的是,删除所有受保护的对象,而不区分它存在于哪一层。我知道这可能是一个危险的操作。但我能在没有复杂解决方案的情况下实现这一点吗。提前谢谢。

  • 我有一个名为 Article 的实体类,另一个名为 ArticleTag 的实体。这两个实体是许多多属性关系,这意味着许多文章可以链接到同一个标签,并且许多标签可以与同一篇文章相关联。 在我的文章实体中,我有以下内容: 在我的ArticleTag实体中,我有这个: 当我的控制器被调用来删除一篇文章时,我在我的ArticleDao类中使用了一个方法,该方法基本上正在这样做: 但是,我的文章无法删除。