At the language level, Java Card is a precise subset of Java: all language constructs of Java Card exist in Java and behave identically. This goes to the point that as part of a standard build cycle, a Java Card program is compiled into a Java class file by a Java compiler; the class file is post-processed by tools specific to the Java Card platform. However, many Java language features are not supported by Java Card (in particular types char, double, float and long; the
transient qualifier;
enums;
arrays of more than one dimension;
finalization; object cloning;
threads). Further, some common features of Java are not provided at runtime by many actual smart cards (in particular type int, which is the default type of a Java expression; and
garbage collection of objects).
Bytecode Java Card bytecode run by the Java Card Virtual Machine is a functional subset of
Java 2 bytecode run by a standard Java Virtual Machine but with a different encoding to optimize for size. A Java Card applet thus typically uses less bytecode than the hypothetical Java applet obtained by compiling the same Java source code. This conserves memory, a necessity in resource constrained devices like smart cards. As a design tradeoff, there is no support for some Java language features (as mentioned above), and size limitations. Techniques exist for overcoming the size limitations, such as dividing the application's code into packages below the 64
KiB limit.
Library and runtime Standard Java Card class library and runtime support differs a lot from that in Java, and the common subset is minimal. Most
packages offered in the Java SE
standard library are not present. For example, the Java Security Manager class is not supported in Java Card, where security policies are implemented by the Java Card Virtual Machine; and transients (non-persistent, fast RAM variables that can be class members) are supported via a Java Card class library, while they have native language support in Java. For example, Java Card has no String type, only byte[] (similar to
C, where
C strings are represented as char[]). Most primitives are absent except for byte, short, int and boolean.
The java.lang package contains fundamental classes of the Java Card technology, which include the two classes Object (the root of the class hierarchy), Throwable (which has only one known subclass Exception, as Error is not present) and relevant exceptions. As mentioned earlier, java.lang.String does not exist in Java Card due to the limitations of the platform, instead representing strings as byte[]. Arrays (T[]) have the length field. There are no wrapper classes Byte, Short, Integer and Boolean for the primitive types byte, short, int and boolean. All exceptions except java.io.IOException and javacard.framework.CardException are instances of java.lang.RuntimeException. The package java.rmi features the interface Remote for methods which are invoked from a card acceptance device (CAD) client application.
The javacard.framework package contains the framework of classes for creating Java Card applets. The Applet is an abstract class for an applet. The Util class contains utility methods on byte arrays (byte[]) and shorts. The javacard.security package contains interfaces and classes for working with cryptographic and security functionality.
These are extension packages to supplement the javacard.* packages. The javacardx.framework.* packages contain various utilities, such as class javacardx.framework.math.BigNumber (operations on Big Numbers), javacardx.framework.nio (a package for buffers, containers for data), javacardx.framework.string.StringUtil (a class providing methods on UTF-8 encoded strings, still represented as byte[]), package javacardx.framework.time which contains classes SysTime (for system time) and TimeDuration (for representing an amount of time), and javacardx.framework.util.intx.JCint for working with int. The javacardx.security.* packages contains functionality for working with certificates, cryptographic derivation functions, and more. The javacardx.biometry contains functionality for biometric frameworks on Java Card. The class javacardx.biometry.BioBuilder is used for creating biometric reference templates, and contains various constants representing different biometric identification means.
Specific features The Java Card runtime and virtual machine also support features that are specific to the Java Card platform: ; Persistence: With Java Card, objects are by default stored in persistent memory (RAM is very scarce on smart cards, and it is only used for temporary or security-sensitive objects). The runtime environment as well as the bytecode have therefore been adapted to manage persistent objects. ; Atomicity: As smart cards are externally powered and rely on persistent memory, persistent updates must be atomic. The individual write operations performed by individual bytecode instructions and API methods are therefore guaranteed atomic, and the Java Card Runtime includes a limited transaction mechanism. ; Applet isolation: The Java Card firewall is a mechanism that isolates the different applets present on a card from each other. It also includes a sharing mechanism that allows an applet to explicitly make an object available to other applets.
Development Coding techniques used in a practical Java Card program differ significantly from those used in a Java program. Still, that Java Card uses a precise subset of the Java language speeds up the learning curve, and enables using a Java environment to develop and debug a Java Card program (caveat: even if debugging occurs with Java bytecode, make sure that the class file fits the limitation of Java Card language by converting it to Java Card bytecode; and test in a real Java Card smart card early on to get an idea of the performance); further, one can run and debug both the Java Card code for the application to be embedded in a smart card, and a Java application that will be in the host using the smart card, all working jointly in the same environment.
Example This is a
"Hello, World!" program example in Java Card. package org.wikipedia.examples; import javacard.framework.APDU; import javacard.framework.Applet; import javacard.framework.ISO7816; import javacard.framework.ISOException; import javacard.framework.Util; public class HelloWorldApplet extends Applet { // INS (instruction) byte for "say hello" final static byte HELLO_INS = (byte)0x01; // AID (Application Identifier) for the applet private static final byte[] HELLO_APPLET_AID = { (byte)0xA0, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x62, (byte)0x03, (byte)0x01, (byte)0x0C, (byte)0x01 }; protected HelloWorldApplet() { register(); } public static void install(byte[] byteArray, short byteOffset, byte byteLength) { // the reference does not need to be assigned // we only need to call the constructor HelloWorldApplet app = new HelloWorldApplet(); } public void process(APDU apdu) { byte[] buffer = apdu.getBuffer(); if (selectingApplet()) { return; } byte ins = buffer[ISO7816.OFFSET_INS]; if (ins == HELLO_INS) { sendHello(apdu); } else { ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED); } } private void sendHello(APDU apdu) { byte[] buffer = apdu.getBuffer(); byte[] hello = { 'H', 'e', 'l', 'l', 'o' }; short length = (short)hello.length; Util.arrayCopyNonAtomic(hello, (short)0, buffer, (short)0, length); apdu.setOutgoingAndSend((short)0, length); } } == Versions ==