关于没有垃圾收集器,我很困惑,定义字段和变量的最佳方法是什么?
我们知道,在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);
}
}
答案 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节 详情。