Attention: The Purifier project has been re-tasked as a commercial product, Purifier2. The original, open source, Purifier1 version is still available. However, for technical reasons, it cannot be made to guarantee that the results are always identical to Sun's preverifier. The Purifier2 commercial version, which is still under development, uses a significantly different architecture to provide better compatibility. See the Project Status section of the Home page for more details.
The following documentation is from the original Purifier1 project and is provided for those who are interested in the project despite its current status.
If you don't know what a CLDC preverifier is, you probably won't know what the Purifier1 is all about. For those of you who do know about J2ME and the role of a preverifier in CLDC software development, the Purifier1 can be described as an open source, pure Java, minimal, CLDC preverifier. The Purifier1 is a program and API that does the absolute minimum required by the CLDC 1.0 specification to convert a compiled Java class file into a file that will work in a CLDC compatible virtual machine. The Purifier1 assumes the given class file has already been checked by a J2SE verifier and does not contain any illegal class references or data types. What that leaves is a program that will inline code from jsr and jsr_w's and create a Stack Map entry for every method that needs one.
If you're new to the world of J2ME software development, a little more explanation is required. First of all, J2ME stands for Java 2 Micro Edition. This is the version of the Java Language and Runtime environment that is indended for hardware smaller than the typical desktop system. The current focus of J2ME is for devices like pagers, cell phones and Personal Digital Assistants. However, J2ME is organized in such a way that it is intended to work with a much wider range of devices like set-top boxes, car stereos and embedded devices. Since J2ME covers such a wide range of devices, it is broken up into several groupings and subgroupings known as Configurations and Profiles. Most cell phones and pagers use the Connected, Limited Device Configuration (CLDC). For more details see http://java.sun.com/j2me/.
One characteristic that most of the CLDC devices have in common is that they usually do not have the processing power that is common in desktop computers. This is a major handicap for the Java Runtime environment because it was originally designed with a high degree of security in mind. One of the security features is that the Java Runtime environment has a built-in verifier. The verifier checks all Java classes when they are loaded to make sure that they conform to various rigorous standards that are intended to ensure that the programs are well behaved and cannot harm the device, other programs or access data that they aren't supposed to be able to access. Although this is a major improvement over other systems, it is a problem for small devices like cell phones because the verification process requires a lot of computing resources, which most cell phones don't have.
The CLDC solution to the problem of verification on low resource hardware is to do some of the verification during the development process so that the on-device verification process can be less resource intensive. This off-device verification is known as preverification and is the task that the Purifier1 is intended to perform.
One of the most resource intensive parts of the verification process is the Data Flow Analysis. Data Flow Analysis (DFA) is the process of discovering what data types are used by the Java Virtual Machine (JVM) at various parts of the program. This requires that there also be a Control Flow Analysis (CFA), which determines what order the instructions in the program will be executed. Since there are many instructions, known as branch instructions, that can alter, or control, the flow of execution through the program depending on the state of the JVM at runtime, the DFA requires an iterative CFA process that determines all of the possible execution paths through the program and all of the possible data types in the JVM for each of those paths and reconcile the differences with what is required. The verifier uses this analysis to check data integrity and consistency regardless of the execution path followed at runtime.
To reduce the burden of Data Flow Analysis for limited on-device verifiers, the preverifier creates a "Stack Map" that is essentially a table of snap-shots of the DFA performed at software development time. The Stack Map is added to the code attributes of each method that has branching instructions so that the on-device verifier can perform a DFA on the device in a single pass, using the Stack Map as a sort of cheat-sheet to help it figure out what the data types should be at the branch points without having to examine all of the other possibile paths to that point in the program. It is a large portion of the Purifier1's job to generate this Stack Map attribute.
Another computing resource hog in the verification process is caused by the subroutine mechanism that the JVM uses for supporting finally blocks in the Java Language. The use of subroutines significantly increases the complexity and resource usage of the verification process. That is why the CLDC specification mandates the inlining of all subroutines.
These two techniques, inlining subroutines and adding a Stack Map allow for a simplified on-device verifier that can verify a class file in a single pass with significantly reduced memory requirements.
The original impetus for the Purifier1 project was that Sun's Java 2 Micro Edition Wireless Toolkit has a preverifier that is written in C. It's always good to have Java development tools that are written in Java so that development can be as platform independent as Java itself. The original toolkit actually had a preverifier that only worked on Windows, which is completely unacceptable to many developers. Although version 1.0.4_01 of the toolkit now includes a Linux and Solaris preverifier, there are many platforms, such as Mac OS X, that have no preverification support from Sun at all. Data Representations makes Java development tools that are pure Java, however, their Simplicity™ for Palm OS® Platform, Simplicity™ for Mobile Devices, products and derivatives are not completely portable like the rest of the Simplicity™ line of products are because of the platform limitations of the preverifier.
Another issue is that J2ME provisioning servers, such as mCentric's, need to be able to dynamically modify and wrap existing J2ME applications. After manipulating the byte code in a J2ME application class file it has to be re-preverified. Running Sun's preverifier on a high volume, mission critical server isn't a viable proposition. This is because it isn't very efficient to spawn a shell to run preverify.exe in for each request. Also, most telco's use "big iron" servers for such things, so they can't run a windows .exe anyways. The Purifier1 should help in these situations because it will be able to run on any J2EE server regardless of platform.
Finally, the Purifier1 is a really fun project. It gets into areas of Java that most programmers never get to work in. I view the Purifier1 as a challenging project and have had a lot of fun and satisfaction from working on it.
The support of mCentric and Data Representations, has made it possible to get started on the Purifier1 project.
This product includes software developed by the Apache Software Foundation (http://www.apache.org/), but is not endorsed or promoted by the Apache Software Foundation.
The Purifier1 project is distributed under the Apache Software License, Version 1.1.