编写Java卡小程序的有效方法是什么?

时间:2015-03-11 09:18:11

标签: java javacard

关于没有垃圾收集器,我很困惑,定义字段和变量的最佳方法是什么? 我们知道,在Java Card技术中,那些使用new关键字分配的对象在超出范围时变得无法访问,但它们占用的存储空间将永远不会被回收。

现在,假设我想发送“你好”。接收每个APDU命令。

这些实现(内存和CPU消耗)之间有什么区别?哪一个最好,为什么?

1-

public class SimpleApp extends Applet {
    byte[] hello = { (byte) 'H', (byte) 'e', (byte) 'l', (byte) 'l', (byte) 'o' };;

    private SimpleApp() {
    }

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

    public void process(APDU arg0) throws ISOException {
        byte[] buffer = arg0.getBuffer();
        Util.arrayCopyNonAtomic(hello, (short) 0, buffer, (short) 0, (short) 5);
        arg0.setOutgoingAndSend((short) 0, (short) 5);
    }
    }

2-

public class SimpleApp extends Applet {
    static byte[] hello = { (byte) 'H', (byte) 'e', (byte) 'l', (byte) 'l', (byte) 'o' };;

    private SimpleApp() {
    }

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

    public void process(APDU arg0) throws ISOException {
        byte[] buffer = arg0.getBuffer();
        Util.arrayCopyNonAtomic(hello, (short) 0, buffer, (short) 0, (short) 5);
        arg0.setOutgoingAndSend((short) 0, (short) 5);
    }

}

3 -

public class SimpleApp extends Applet {
    byte[] hello = { (byte) 'H', (byte) 'e', (byte) 'l', (byte) 'l', (byte) 'o' };;

    private SimpleApp() {
    }

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

    public void process(APDU arg0) throws ISOException {
        byte[] buffer = new byte[255];
        buffer = arg0.getBuffer();
        Util.arrayCopyNonAtomic(hello, (short) 0, buffer, (short) 0, (short) 5);
        arg0.setOutgoingAndSend((short) 0, (short) 5);
    }

}

4-

public class SimpleApp extends Applet {
    static byte[] hello = { (byte) 'H', (byte) 'e', (byte) 'l', (byte) 'l', (byte) 'o' };;
    byte[] buffer;
    private SimpleApp() {
    }

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

    public void process(APDU arg0) throws ISOException {
        buffer = arg0.getBuffer();
        Util.arrayCopyNonAtomic(hello, (short) 0, buffer, (short) 0, (short) 5);
        arg0.setOutgoingAndSend((short) 0, (short) 5);
    }

}

5 -

public class SimpleApp extends Applet {
    static byte[] hello = { (byte) 'H', (byte) 'e', (byte) 'l', (byte) 'l', (byte) 'o' };;
    static byte[] buffer;
    private SimpleApp() {
    }

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

    public void process(APDU arg0) throws ISOException {
        buffer = arg0.getBuffer();
        Util.arrayCopyNonAtomic(hello, (short) 0, buffer, (short) 0, (short) 5);
        arg0.setOutgoingAndSend((short) 0, (short) 5);
    }

}

1 个答案:

答案 0 :(得分:4)

版本1: 缓冲区存储在EEPROM中作为实例变量。这没关系。

版本2: 缓冲区存储在EEPROM中作为类变量。这没关系。

但是,这里提到的静态字段可能存在一些安全问题https://community.oracle.com/thread/1752580

  

JCRE创建由任何应用程序实例共享的上下文   属于一个包。他们被防火墙分开,所以任何   应用程序在另一个上下文中无法访问静态变量和   方法不属于实例,属于类本身所以   超出了防火墙的范围,任何人都可以访问   应用在智能卡中。所以我们正在处理严重的安全问题   风险。

或此处:http://pfa12.free.fr/doc_java/javacard_specifications/specs/jcre/html/JCRESpec06firewall.html(第6.1.6章)

  

类 - 对象的实例 - 由上下文拥有;课本身   不是。没有运行时上下文检查可以在何时执行   访问类静态字段。也没有上下文切换   当调用静态方法时。 (同样,调用特殊原因没有   上下文切换。)

     

可以从任何公共静态字段和公共静态方法访问它们   context:静态方法在与调用者相同的上下文中执行。

     

静态字段中引用的对象只是常规对象。他们是   由任何人创建它们和标准防火墙访问规则   应用。如果有必要在多个上下文中共享它们,那么   这些对象需要是可共享的接口对象(SIO)。

上述文字并不意味着您根本不能使用静态字段和方法。你只需要仔细考虑它。另一件事是对实例的静态引用可能是危险的:它们可能导致一种情况,当你的applet无法删除时,如下所述:http://askra.de/software/jcdocs/app-notes-2.2.2/garbagecoll.html

  

删除applet意味着applet及其所有子对象   被删除。如果满足以下任一条件,则Applet删除失败   存在:

     
      
  • applet实例拥有的任何对象都由卡上另一个applet实例拥有的对象引用。

  •   
  • applet实例拥有的任何对象都是从卡上任何包中的静态字段引用的。

  •   

版本3: 每个APDU在EEPROM中创建一个新缓冲区。一个非常糟糕的主意。没有垃圾收集器,由于缺少EEPROM,你的applet很快就会失败。使用垃圾收集器,您的applet将非常慢。仅在applet构造函数中或在初始“存储数据”阶段分配新实例。

版本4,5: 这根本不起作用。这会导致异常。您不能将APDU缓冲区引用存储在类或实例变量中:

  

对APDU缓冲区字节数组的引用不能存储在类中   变量或实例变量或数组组件。请参阅运行时   Java Card平台的环境规范,第6.2.2节   详情。