Retrotranslator |
![]() |
Retrotranslator is a tool that makes Java applications compatible with various versions of the Java platform. It supports all Java 5 language features and a significant part of Java 5 API on J2SE 1.4. In other Java environments only the Java 5 language features that does not require new API are supported. Retrotranslator is based on the ASM bytecode manipulation framework and the backport of concurrency utilities.
Retrotranslator-n.n.n-bin.zip
,
where n.n.n is the latest Retrotranslator release number.
myclasses
.
java -jar retrotranslator-transformer-n.n.n.jar -srcdir myclasses
retrotranslator-runtime-n.n.n.jar
and
backport-util-concurrent-n.n.jar
into the classpath of your application.
The command line syntax:
java -jar retrotranslator-transformer-n.n.n.jar <options>
or
java -cp retrotranslator-transformer-n.n.n.jar
net.sf.retrotranslator.transformer.Retrotranslator <options>
Option | Description | Default |
---|---|---|
-srcdir <path> |
The directory with the files to process (may be specified several times). | - |
-srcjar <file> |
The JAR archive file with the files to process (may be specified several times). | - |
-destdir <path> |
The directory to place processed files. | The source directory. |
-destjar <file> |
The JAR archive file to place processed files. | The source JAR file. |
-srcmask <mask> |
The wildcard pattern specifying the files to transform rather than copy
(classes or UTF-8 text files), e.g. *.class;?*.tld .
|
*.class |
-target <version> |
The version of the JVM where classes should be able to run. The supported targets are 1.1, 1.2, 1.3, 1.4, and 1.5. While API support is available only for the 1.4 target, user-defined backport classes may be used for other targets as well. | 1.4 |
-classpath <path> |
The dependencies of the translated classes, including the target JVM and Retrotranslator itself.
The following files should be specified among others if the target is Sun JRE 1.4: rt.jar ,
jce.jar , jsse.jar , retrotranslator-runtime-n.n.n.jar ,
and backport-util-concurrent-n.n.jar .
This option may be omitted if the current Java environment matches the target one.
|
The current classpath. |
-verify |
Asks the translator to examine translated bytecode for references to classes, methods, or fields that cannot be found in the classpath. | false |
-support <features> |
Enables advanced features. The names specified should be separated with semicolons, e.g.
ThreadLocal.remove;BigDecimal.setScale .
|
- |
-advanced |
Enables all advanced features at once, but it's recommended to enable only required features in order to avoid compatibility issues. | false |
-smart |
Makes all backport classes inheritable provided that the classpath
correctly reflects the target environment.
For example, the backport of the Writer.append(String) method may be used
to translate the following expression: new FileWriter("file.tmp").append("Hello") .
|
false |
-backport <names> |
The backport names separated with semicolons, e.g.
com.myco.all;java.util:com.myco.ju;javax.net.SocketFactory:com.myco.jsse.Factory .
The corresponding backport classes must be present in the classpath.
|
- |
-embed <package> |
The package name for a partial copy of retrotranslator-runtime-n.n.n.jar and
backport-util-concurrent-n.n.jar to be put along with translated classes.
This makes an application independent of other versions of Retrotranslator present in the classpath.
|
- |
-lazy |
Asks the translator to transform and verify only the classes compiled with a target greater than the current one. | false |
-stripsign |
Asks the translator to strip signature (generics) information. | false |
-verbose |
Asks the translator for verbose output. | false |
-retainapi |
Asks the translator to modify classes for JVM compatibility but keep use of API
unless the backport option is specified.
Any references introduced by a compiler remain unchanged, like the use of
java.lang.StringBuilder for string concatenation or
the implicit valueOf method calls for autoboxing.
|
false |
-retainflags |
Asks the translator to keep Java 5 specific access modifiers. | false |
-uptodatecheck |
Asks the translator to skip processing of files if the destination files are newer. | false |
If you have myapplication5.jar
file built with Java 5 you can use the following command to produce
myapplication4.jar
. It will be compatible with Java 1.4 and independent of Retrotranslator because
backport classes are added to the translated application with a different package name:
java -jar retrotranslator-transformer-n.n.n.jar
-srcjar myapplication5.jar -destjar myapplication4.jar -embed com.mycompany.internal
Also it is recommended to specify the classpath and verify options. In case of verification failure try the smart and advanced options.
The distribution contains an Apache Ant task
net.sf.retrotranslator.transformer.RetrotranslatorTask
. Every command line
option can be set using the corresponding attribute. In addition the source files can be specified with nested
fileset
, jarfileset
, and dirset
elements and the
classpath can be set with nested classpath
elements or the classpathref
attribute.
The source directories specified with srcdir
, dirset
,
and the dir
attribute of fileset
should contain the root package of the classes.
In case of warnings the build fails unless the value of
the failonwarning
attribute is set to false
. For example:
<path id="classpath"> <fileset dir="lib" includes="**/*.jar"/> </path> <taskdef name="retrotranslator" classpathref="classpath" classname="net.sf.retrotranslator.transformer.RetrotranslatorTask" /> <retrotranslator destdir="build/classes14" verify="true" failonwarning="false"> <fileset dir="build/classes15" includes="**/*.class"> <jarfileset dir="build/lib15" includes="**/*.jar"> <classpath location="${java14_home}/jre/lib/rt.jar"/> <classpath refid="classpath"/> </retrotranslator>
For Maven there is a Retrotranslator plugin from the Mojo Project.
There is a plugin to automatically translate and verify classes compiled by IntelliJ IDEA, so you can develop in Java 5 but run and debug on JRE 1.4.
In order to run a Java 5 application on J2SE 1.4 start it with JIT Retrotranslator:
java -cp retrotranslator-transformer-n.n.n.jar
net.sf.retrotranslator.transformer.JITRetrotranslator
<options> -jar <jarfile> [<args...>]
java -cp retrotranslator-transformer-n.n.n.jar:<classpath>
net.sf.retrotranslator.transformer.JITRetrotranslator
<options> <class> [<args...>]
The options can include support
,
advanced
, smart
, and
backport
. When running on J2SE 5.0 JIT Retrotranslator simply calls
the application, but on J2SE 1.4 it also translates classes compiled for Java 5 or later. However this capability
depends on the current JVM and the application itself, so under certain conditions JIT Retrotranslator may be unable
to translate either a JAR file or classes from the classpath or both.
Package | Class | Methods and fields | Compatibility notes |
---|---|---|---|
java.io |
Closeable2
|
* (all methods) | |
Flushable2 |
* | ||
PrintStream |
* (11 new methods and constructors) | ||
PrintWriter |
* (11 new methods and constructors) |
The PrintWriter.format and PrintWriter.printf methods always flush the output buffer.
|
|
Reader |
* (1 new method) | ||
Writer |
* (3 new methods) | ||
java.lang |
Appendable2 |
* | |
Boolean |
* (2 new methods) | ||
Byte |
* (1 new method) | ||
Character |
* (44 new methods) | New members of Character.UnicodeBlock are not supported.
All supplementary code points are considered as unassigned.
|
|
Class |
* (21 new methods) |
Enable features "Class.getMethod " and "Class.getDeclaredMethod " for more
uniform support of generics and covariant return types on different platforms3.
|
|
Deprecated |
* | ||
Double |
valueOf(double) |
||
Enum |
* | ||
Float |
valueOf(float) |
||
IllegalArgumentException |
* (2 new constructors) | ||
IllegalStateException |
* (2 new constructors) | ||
Integer |
valueOf(int), |
||
Iterable2 |
* | ||
Long |
valueOf(long), |
||
Package |
* (4 new methods) | ||
Readable2 |
* | ||
Short |
* (2 new methods) | ||
StackTraceElement |
* (1 new constructor) | ||
String |
* (10 new methods and constructors)
isEmpty()4
|
||
StringBuffer |
* (11 new methods and constructors) |
Enable feature "StringBuffer.trimToSize " to use an empty implementation of
the StringBuffer.trimToSize() method3.
|
|
StringBuilder |
* | StringBuilder is replaced with StringBuffer . |
|
SuppressWarnings |
* | ||
System |
nanoTime()1, |
The System.nanoTime() method precision
may vary on different platforms.
|
|
Thread |
* (8 new methods) |
The Thread.getId() method does not reflect the order in which threads are created.The Thread.getStackTrace() and Thread.getAllStackTraces()
methods return non-empty stack trace only for the current thread.Enable feature " Thread.getState " to support the Thread.getState() method, but it may
be able
to detect only NEW , RUNNABLE and TERMINATED states.3Enable features " Thread.setUncaughtExceptionHandler " and
"Thread.setDefaultUncaughtExceptionHandler " to support exception handlers for threads
created by translated code (in contrast to J2SE 5.0 the default UncaughtExceptionHandler
takes precedence over ThreadGroup )3.
|
|
Thread.State |
* | ||
Thread.UncaughtExceptionHandler2 |
* | ||
ThreadLocal |
* (1 new method) | Enable feature "ThreadLocal.remove " to use alternative ThreadLocal
and InheritableThreadLocal implementations with method
remove() 3.
|
|
TypeNotPresentException |
* | ||
java.lang.annotation |
* (all classes) | * | |
java.lang.instrument |
* | * | Bytecode instrumentation is not implemented. |
java.lang.management |
ManagementFactory |
getPlatformMBeanServer() |
The ManagementFactory.getPlatformMBeanServer() method simply returns
the first registered MBeanServer or creates it when no one exists.
An implementation of JMX 1.2 must be present in a classpath.
|
java.lang.ref |
SoftReference |
* |
Enable feature "SoftReference.NullReferenceQueue " to
support null for the second parameter of
SoftReference(Object,ReferenceQueue)
on all platforms3.
|
WeakReference |
* |
Enable feature "WeakReference.NullReferenceQueue " to
support null for the second parameter of
WeakReference(Object,ReferenceQueue)
on all platforms3.
|
|
java.lang.reflect |
AccessibleObject |
* (4 new methods) | |
AnnotatedElement2 |
* | ||
Constructor |
* (11 new methods) | ||
Field |
* (8 new methods) | ||
GenericArrayType |
* | ||
GenericDeclaration2 |
* | ||
GenericSignatureFormatError |
* | ||
MalformedParameterizedTypeException |
* | ||
Method |
* (14 new methods) | ||
ParameterizedType |
* | ||
Type2 |
* | ||
TypeVariable |
* | ||
WildcardType |
* | ||
java.math |
BigDecimal |
ZERO, ONE, TEN, |
Enable feature "BigDecimal.setScale " to support negative scales in method
BigDecimal.setScale(int, int) 3.
|
BigInteger |
TEN |
||
java.net |
HttpURLConnection |
* (6 new methods) |
Enable features "HttpURLConnection.setChunkedStreamingMode ",
"HttpURLConnection.setFixedLengthStreamingMode "
to use the corresponding methods, but on Java 1.4 they will simply return.
Consider using alternative or writing own protocol handlers.
|
Proxy |
* | ||
ProxySelector |
* | ||
URL |
* (2 new methods) | The Proxy is ignored by the
URL.openConnection(Proxy) method.
|
|
URLConnection |
* (4 new methods) |
Enable features "URLConnection.getConnectTimeout ", "URLConnection.setConnectTimeout ",
"URLConnection.getReadTimeout ", "URLConnection.setReadTimeout "
to use the corresponding methods, but on Java 1.4 they will simply return.
Consider using alternative or writing own protocol handlers.
|
|
java.nio |
CharBuffer |
* (4 new methods) | |
Charset |
* (1 new method) | The Charset.defaultCharset() method returns UTF-8
if the default charset is unavailable (occurs on JDK 1.4.0).
|
|
java.rmi.server |
RemoteObjectInvocationHandler |
* | |
java.text |
DecimalFormat |
* (2 new methods) |
Enable feature "DecimalFormat.setParseBigDecimal " to support the
DecimalFormat.setParseBigDecimal(boolean) method, but
parsing and formatting precision will still be limited by the java.lang.Double
or java.lang.Long precision3.
|
java.util |
AbstractQueue1 |
* | |
ArrayDeque1,4 |
* | ||
Arrays |
* (21 new methods)copyOf(...) 4 (10 methods)copyOfRange(...) 4 (10 methods)
|
||
Collections1 |
* (13 new methods)newSetFromMap(Map) 4
|
||
Deque1,2,4 |
* | ||
EnumMap |
* | ||
EnumSet |
* | ||
Formatter |
* | ||
LinkedList |
* (5 new methods) | ||
PriorityQueue1 |
* | ||
Properties |
* | ||
Queue1,2 |
* | ||
Timer |
* (3 new methods and constructors) |
Enable feature "Timer.All " to use alternative Timer
and TimerTask implementations in order to be able to call Timer(String) ,
Timer(String, boolean) , and Timer.purge() 3.
|
|
UUID |
* | ||
java.util.concurrent, |
almost all classes1 | almost all methods | The LockSupport class may be unusable due to insufficient performance.
The Condition.awaitNanos(long) method has
little accuracy guarantees.
|
java.util.regex |
Matcher |
quoteReplacement(String), |
|
MatchResult2 |
* | ||
Pattern |
quote(String) |
||
javax.net.ssl |
HttpsURLConnection |
* (2 new methods) |
1 Supported via the
Backport of JSR 166.
2 In most cases this type is replaced with its base type.
3 Supported only when the corresponding feature is enabled via the
support
or
advanced
options.
4 Introduced in Java 6.
In order to support API unavailable on the target platform Retrotranslator should be able to replace all references
to new clases, constructors, methods, and fields with references to backports compatible with the platform.
The location of the backports must be specified with the classpath option. The
default
backports for the 1.4 target have been packaged into the retrotranslator-runtime-n.n.n.jar
and
backport-util-concurrent-n.n.jar
files, and to complement or override them additional backport
names may be specified via the backport option. The backport names may have five
different forms, the first one declares a universal backport package and the others allow to reuse existing backports.
Backport name form | Example |
---|---|
<universal backport package name> |
net.sf.retrotranslator.runtime |
<original package name>:<backport package name> |
java.util.concurrent:edu.emory.mathcs.backport.java.util.concurrent |
<original class name>:<backport class name> |
java.lang.StringBuilder:java.lang.StringBuffer |
<original method name>:<backport method name> |
java.lang.System.nanoTime:edu.emory.mathcs.backport.java.util.concurrent.helpers.Utils.nanoTime |
<original field name>:<backport field name> |
java.util.Collections.EMPTY_MAP:edu.emory.mathcs.backport.java.util.Collections.EMPTY_MAP |
The names of backport classes in a universal backport package consist of the backport package name,
the name of the original class, and an optional trailing underscore. For example,
net.sf.retrotranslator.runtime.java.util.EnumSet_
is a complete backport of
java.util.EnumSet
.
But when classes exist on the target platform then the backports of their new fields, constructors and methods are
grouped into classes with a leading underscore in their names. Look at the
net.sf.retrotranslator.runtime.java.math._BigDecimal
class:
convertConstructorArguments
method that
accepts constructor's arguments an returns an argument for a Java 1.4 constuctor.
The
net.sf.retrotranslator.runtime.java.io._PrintStream
and
net.sf.retrotranslator.runtime.java.lang._SecurityException
classes use another type of
constructor backports. There is a public static
createInstanceBuilder
method that accepts constructor's arguments an returns an object with public
argument1
...argumentN
methods and an optional public void initialize
method.
All the argumentX
methods provide arguments for a Java 1.4 constuctor and should not have any
parameters. The initialize
method has a single parameter for the created instance and may be used for
postprocessing. If this approach does not work there is another flexible but not always supported one used by
net.sf.retrotranslator.runtime.java.lang._StackTraceElement
.
If backported methods require access to non-public methods or fields of the instance, they can do it with reflection
when the security manager allows such access. The backports of public instance fields are not supported, but private
instance fields can be emulated using a weak identity map, see
net.sf.retrotranslator.runtime.java.lang._Thread
for an example.
Copyright (c) 2005 - 2007 Taras Puchko All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.