In the article PCSC sample in Java I presented the javax.smartcardio package to use PC/SC from a Java application. It works except that SUN/Oracle made 2 mistakes related to the same problem: PC/SC is an API not an ABI.
APIAn API is an interface used at the source code level. In C langage, you include a header file and link to the associated library. In the PC/SC case you use something like:
#ifdef __APPLE__ #include <PCSC/winscard.h> #include <PCSC/wintypes.h> #else #include <winscard.h> #endif
And then use the PC/SC functions as provided in the header file.
ABIThe ABI is an interface used at the binary level.
At the API level the type
intis used. At the ABI level the representation of
intis used. The difference is that the C language do not define what
intis. At the ABI level the representation of
intis fixed by the compiler.
Evolution of API and/or ABIThe API may evolve if a new function is added, an existing function is removed or a function signature is changed (a function parameter is added or removed for example).
Each time the API change the ABI also changes. The ABI may also evolve even if the API do not change. This is more rare but happened with C++ when GCC changed the way to pass parameters to a function/method.
To avoid incompatibility problems on GNU/Linux the library contains an versioning. It is called soname. Applications using the old API/ABI will use libfoo version n. Applications using the new API/ABI will use libfoo version n+1. It is possible to have the two library versions installed at the same time (I don't know if it is possible to do that on a Windows system).
The JVM problemsSUN/Oracle made 2 mistakes in its use of the PC/SC library.
Direct use of libpcsclite.soAs written above a library is versioned. In the case of PC/SC the library is called
libpcsclite.so.1on a GNU/Linux system. The previous version was
libpcsclite.so.0.I changed the API in version 1.2.9-beta1 (May 2004). I then increased the ABI version from 0 to 1.
libpcsclite.sois a symbolic link pointing to the version corresponding to the installed header files. Only the linker should use that file when building an application. On a Debian (or Ubuntu) system the file
libpcsclite.sois provided by the
libpcsclite-devpackage and not by the
The Oracle JVM tries to loads
libpcsclite.sodirectly. This is wrong because:
- This file is not installed by default when the PC/SC library is installed
- This file do not reference a particular library version. So if the PC/SC API change again then the JVM will miserably fail.
I get many bug reports because of that. But the problem is not on the pcsc-lite side. So I can't do much.
Direct definition of DWORD
Oracle think a
DWORDis a 64-bit entity on a 64-bit system. This is not always the case and is wrong on Mac OS X in 64-bits mode.
typedef uint32_t DWORD;
On Linux it is defined as:
typedef unsigned long DWORD;
If the application (the JVM in this case) and the library (PCSC framework) do not agree on the ABI (the size of a
DWORDparameter) then bad things happen.
See the bug report javax.smartcardio package not working in Java 7 on OS X ML for a solution to this problem.
ConclusionI wrote this blog article so that I can refer people at it. And so that you can refer Oracle at it.
I do not use Java. I do not know how to report a JVM bug at Oracle. If you know then please send them a link of this article.