You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建仅支持单实例安装的JavaCard小程序?删除后可重装

实现单实例JavaCard小程序的方案

要实现同一时间仅能安装一个实例的JavaCard小程序,核心是利用小程序安装阶段的静态检查逻辑,结合卡内持久化存储的标记控制安装流程——删除实例后标记会随私有存储区被自动清除,从而允许重新安装。

基础实现方案

代码示例

package com.yourpackage;

import javacard.framework.*;

public class SingleInstanceApplet extends Applet {
    // 存储在EEPROM的实例存在标记,删除小程序时会被卡系统自动清除
    private static boolean instanceCreated;

    protected SingleInstanceApplet() {
        register();
    }

    public static void install(byte[] bArray, short bOffset, byte bLength) throws ISOException {
        // 检查是否已有实例存在
        if (instanceCreated) {
            // 抛出标准错误码阻止重复安装
            ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED);
        }
        // 标记实例已创建
        instanceCreated = true;
        // 初始化并注册小程序
        new SingleInstanceApplet();
    }

    public void process(APDU apdu) throws ISOException {
        byte[] buf = apdu.getBuffer();
        if (selectingApplet()) {
            return;
        }

        // 处理业务APDU命令
        switch (buf[ISO7816.OFFSET_INS]) {
            case (byte)0x01:
                // 示例命令逻辑
                break;
            default:
                ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
        }
    }
}

关键逻辑说明

  • instanceCreated变量:作为静态成员,它会被存储在小程序专属的EEPROM区域。当小程序被删除时,卡系统会回收该区域的所有数据,标记会自动清除,后续可重新安装。
  • 安装阶段检查:install方法是静态入口,创建实例前先检查标记,若已存在则抛出0x6A81(功能不支持)的标准ISO错误码,终端可直接识别该错误。
  • 实例注册:构造方法中调用register()是JavaCard小程序的标准初始化步骤,确保实例被卡系统正确注册。

更严谨的注册表方案

如果需要更可靠的实例检查,可以利用JavaCard的系统注册表存储实例引用:

package com.yourpackage;

import javacard.framework.*;

public class SingleInstanceApplet extends Applet {
    // 唯一注册表键,避免与其他小程序冲突
    private static final byte[] APPLET_INSTANCE_KEY = {(byte)'S',(byte)'I',(byte)'A',(byte)'P'};

    protected SingleInstanceApplet() {
        register();
    }

    public static void install(byte[] bArray, short bOffset, byte bLength) throws ISOException {
        // 尝试从注册表获取已存在的实例
        Object existingInstance = JCSystem.getRegistryEntry(APPLET_INSTANCE_KEY);
        if (existingInstance != null) {
            ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED);
        }

        SingleInstanceApplet applet = new SingleInstanceApplet();
        // 将实例存入系统注册表
        JCSystem.setRegistryEntry(APPLET_INSTANCE_KEY, applet);
    }

    // 可选:手动清除注册表项(卡系统通常会自动处理,此步骤提升兼容性)
    public void uninstall() {
        JCSystem.deleteRegistryEntry(APPLET_INSTANCE_KEY);
        super.uninstall();
    }

    public void process(APDU apdu) throws ISOException {
        // 业务命令处理逻辑
        byte[] buf = apdu.getBuffer();
        if (selectingApplet()) {
            return;
        }
        ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
    }
}

方案优势

  • 利用系统注册表的全局存储特性,能更精准地检测实例是否存在,避免静态变量可能的意外问题。
  • 手动重写uninstall方法清除注册表项,可确保在不同卡系统中的兼容性,虽然多数卡系统会自动清理关联数据。

内容的提问来源于stack exchange,提问作者1chenar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 23:24:37