Retrotranslator |
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 full 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 |
The directory with classes that should be translated (may be specified several times). | - |
-srcjar |
The directory with classes that should be translated (may be specified several times). | - |
-destdir |
The directory to place translated classes. | Location of sources |
-destjar |
The JAR file to place translated classes. | Location of sources |
-advanced |
Whether to use alternative implementations of Java 1.4 classes and methods for better Java 5 compatibility. | Off |
-verify |
Asks the translator to examine translated bytecode for references to classes, methods, or fields that cannot be found in the provided classpath. | Off |
-classpath |
The classpath for verification including rt.jar , jce.jar ,
jsse.jar (from JRE 1.4), retrotranslator-runtime-n.n.n.jar ,
and backport-util-concurrent-n.n.jar . |
Current classpath |
-srcmask |
The wildcard pattern specifying files that should be translated (either bytecode or UTF-8 text),
e.g. "*.class;*.tld ". There are three special characters: "*?; ".
|
*.class |
-embed |
Package name for a private copy of retrotranslator-runtime-n.n.n.jar and
backport-util-concurrent-n.n.jar to be put into -destdir or -destjar .
This makes your application independent of other versions of Retrotranslator present in the classpath.
|
- |
-backport |
Informs the translator about user-defined backport packages. Package names should be separated by semicolons. | - |
-target |
To make Java 6 classes compatible with Java 5 set this option to 1.5 and supply
user-defined backport packages via the backport option. |
1.4 |
-lazy |
Asks the translator to only transform classes compiled with a target greater than the current one. |
Off |
-stripsign |
Asks the translator to strip signature (generics) information. | Off |
-verbose |
Asks the translator for verbose output. | Off |
-retainapi |
Asks the translator to modify classes for JVM 1.4 compatibility but keep use of Java 5 API.
References introduced by a compiler will also remain unchanged,
like the use of java.lang.StringBuilder for string concatenation
or the implicit valueOf method call for autoboxing. |
Off |
-retainflags |
Asks the translator to keep Java 5 specific access modifiers. | Off |
For example, if you have a Java 5 application myapplication5.jar
you can use the following command
to produce myapplication4.jar
that will run on J2SE 1.4 and is independent of Retrotranslator,
since required 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
The distribution contains an integrated Apache Ant task
net.sf.retrotranslator.transformer.RetrotranslatorTask
. It has the following syntax:
Attribute | Description | Default |
---|---|---|
srcdir |
The directory with classes that should be translated. | - |
srcjar |
The directory with classes that should be translated. | - |
destdir |
The directory to place translated classes. | Location of sources |
destjar |
The JAR file to place translated classes. | Location of sources |
advanced |
Whether to use alternative implementations of Java 1.4 classes and methods for better Java 5 compatibility. | Off |
verify |
Asks the translator to examine translated bytecode for references to classes, methods, or fields that cannot be found in the provided classpath. | Off |
classpath |
The classpath for the verification, including rt.jar , jce.jar ,
jsse.jar (from JRE 1.4), retrotranslator-runtime-n.n.n.jar ,
and backport-util-concurrent-n.n.jar .
|
Current classpath |
classpathref |
The classpath for the verification, given as a reference to a path defined elsewhere. | Current classpath |
srcmask |
The wildcard pattern specifying files that should be translated (either bytecode or UTF-8 text),
e.g. "*.class;*.tld ". There are three special characters: "*?; ".
|
*.class |
embed |
Package name for a private copy of retrotranslator-runtime-n.n.n.jar and
backport-util-concurrent-n.n.jar to be put into -destdir or -destjar .
This makes your application independent of other versions of Retrotranslator present in the classpath.
|
- |
backport |
Informs the translator about user-defined backport packages. Package names should be separated by semicolons. | - |
target |
Set this option to 1.5 and supply user-defined backport packages via
the backport option to make Java 6 classes compatible with Java 5. |
1.4 |
lazy |
Asks the translator to only transform classes compiled with a target greater than the current one. |
Off |
stripsign |
Asks the translator to strip signature (generics) information. | Off |
verbose |
Asks the translator for verbose output. | Off |
retainapi |
Asks the translator to modify classes for JVM 1.4 compatibility but keep use of Java 5 API.
References introduced by a compiler will also remain unchanged,
like the use of java.lang.StringBuilder for string concatenation
or the implicit valueOf method call for autoboxing. |
Off |
retainflags |
Asks the translator to keep Java 5 specific access modifiers. | Off |
failonwarning |
Indicates whether the build will fail when there are verification warnings. | On |
You may use nested fileset
, jarfileset
, and dirset
elements to specify
source files and classpath
elements to specify classpath. 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"> <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.
JIT Retrotranslator is able to translate at runtime Java classes loaded with any classloader.
It works on J2SE 1.4 from most JVM vendors like Sun, IBM, BEA, and Apple, but does nothing on J2SE 5.0.
However translation at runtime consumes additional memory and processing resources and it will not
work if your classes make use of Java 5 API but were compiled with "-target 1.4
".
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...>]
JITRetrotranslator.run()
from some JVM 1.4 compatible class
before Java 5 classes are loaded.
JIT Retrotranslator can accept the advanced
and backport
options.
Package | Class | Methods and fields | Compatibility notes |
---|---|---|---|
java.lang.annotation | * (all classes) | * (all methods) | |
java.lang.instrument | * (all classes) | * (all methods) | Bytecode instrumentation is not implemented. |
java.util.concurrent, |
almost all classes1 | almost all methods | The LockSupport class may be unusable due to poor efficiency.
The Condition.awaitNanos(long) method has
little accuracy guarantees. |
java.io | Closeable2
| * | |
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 | read(CharBuffer) | ||
Writer |
append(CharSequence),
| ||
java.lang | Appendable2 | * | |
Boolean | parseBoolean(String), | ||
Byte | valueOf(byte) | ||
Character | valueOf(char) | ||
Class | * (21 new methods) |
Class.getMethod(String, Class...) and Class.getDeclaredMethod(String, Class...)
are intercepted to better support generics and covariant return types
on several platforms3.
| |
Deprecated | * | ||
Double | valueOf(double) | ||
Enum | * | ||
Float | valueOf(float) | ||
IllegalArgumentException | IllegalArgumentException(String, Throwable), | ||
IllegalStateException | IllegalStateException(String, Throwable), | ||
Integer | valueOf(int), signum(int) | ||
Iterable2 | * | ||
Long | valueOf(long), signum(long) | ||
Package | * (4 new methods) | ||
Readable2 | * | ||
Short | valueOf(short) | ||
String | contains(CharSequence), | ||
StringBuffer |
StringBuffer(CharSequence), | ||
StringBuilder |
All methods supported in StringBuffer
| StringBuilder is replaced with StringBuffer . | |
SuppressWarnings | * | ||
System | nanoTime()1, |
The System.nanoTime() method precision
may vary on different platforms.
| |
Thread | getStackTrace(), | The Thread.getStackTrace()
method returns non-empty stack trace only for the current thread.The Thread.getId() method does not reflect the order in which threads are created. | |
Thread.State | * | ||
ThreadLocal | remove()3 |
ThreadLocal and InheritableThreadLocal
are replaced by corresponding classes from the runtime library.3. | |
TypeNotPresentException | * | ||
java.lang.ref |
SoftReference | * |
SoftReference(Object,ReferenceQueue)
supports null for the second parameter
on all platforms3.
|
WeakReference | * |
WeakReference(Object,ReferenceQueue)
supports null for the second parameter
on all platforms3.
| |
java.lang.reflect |
AccessibleObject | * | |
AnnotatedElement2 | * | ||
Constructor | * (11 new methods) | ||
Field | * (8 new methods) | ||
GenericArrayType | * | ||
GenericDeclaration2 | * | ||
GenericSignatureFormatError | * | ||
MalformedParameterizedTypeException | * | ||
Method | * (14 new methods) | ||
ParameterizedType | * | ||
Type2 | * | ||
TypeVariable | * | ||
WildcardType | * | ||
java.math | BigDecimal |
BigDecimal(int), | The BigDecimal.setScale(int, int)
method supports negative scales3. |
java.net | URL |
openConnection(Proxy) ,toURI()
| The Proxy is ignored by the openConnection(Proxy) method. |
Proxy | * | ||
ProxySelector | * | ||
java.rmi.server | RemoteObjectInvocationHandler |
* | |
java.text | DecimalFormat |
isParseBigDecimal()3, |
BigDecimal parsing and formatting precision is limited by
java.lang.Double or java.lang.Long precision.
|
java.util.nio | CharBuffer |
append(CharSequence),
| |
java.util | AbstractQueue1 |
* | |
Arrays | * (21 new methods) | ||
Collections1 | * (13 new methods) newSetFromMap(Map)4 | ||
EnumMap | * | ||
EnumSet | * | ||
Formatter | * | ||
LinkedList | * (5 new methods) | ||
PriorityQueue1 | * | ||
Queue1,2 | * | ||
UUID | * | ||
java.util.regex | Matcher |
quoteReplacement(String), | |
MatchResult2 | * | ||
Pattern | quote(String) |
1 Supported via the
Backport of JSR 166.
2 In most cases this type is being replaced with it's base type.
3 Supported only in advanced mode, i.e. when
the advanced
option is specified.
4 Introduced in Java 6, but available only for 1.4 target.
Since most backported classes are discovered by Retrotranslator at translation time,
you may write an extension and simply put it into the Retrotranslator classpath to make it work.
For example, all references to
java.util.EnumSet
are replaced with references to
net.sf.retrotranslator.runtime.java.util.EnumSet_
(optional trailing underscore) if the latter can be found.
But if you replace a whole class that exists in J2SE 1.4 you may encounter interoperability issues with other libraries.
So, for example, support for Java 5 fields, methods, and constructors of
java.math.BigDecimal
is placed into
net.sf.retrotranslator.runtime.java.math._BigDecimal
(leading underscore):
convertConstructorArguments
method that
accepts constructor's arguments an returns an argument for a Java 1.4 constuctor.
Another approach for constructor backporting is used by
net.sf.retrotranslator.runtime.java.io._PrintStream
. There is a public static
createInstanceBuilder
method that accepts constructor's arguments an returns an object with public
argument1
...argumentN
methods and optional public void initialize
method.
All 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.
However, if the backported methods require access
to non-public methods or fields of the instance, they cannot be fully handled by Retrotranslator.
While you can use reflection to access any data, translated code generally should not depend on security settings.
For example, it is impossible to write an implementation for methods getSource()
and setSource()
of java.beans.PropertyEditorSupport
that will work in any environment.
Also this approach cannot be used to replace instance field references.
You can put your extensions into packages other than net.sf.retrotranslator.runtime
.
For example, specify the following at the command line to make Retrotranslator use
com.mycompany.internal.java.lang._String
and to rewrite all references to
com.sun.org.apache.xerces.internal.*
with org.apache.xerces.*
:
-backport com.mycompany.internal;com.sun.org.apache.xerces.internal:org.apache.xerces
If you have written an extension that does not contain copyrighted code, you may send a patch under the Retrotranslator license.
Basically, only classes, methods, and fields listed above should work, and other features, like formatted input, are not supported. Known issues:
java -Djava.version=1.5.0 -Djava.specification.version=1.5 -Djava.class.version=49.0 ...
((Writer) new FileWriter("file.tmp")).append("Hello").close();
Retrotranslator: a Java bytecode transformer that translates Java classes compiled with JDK 5.0 into classes that can be run on JVM 1.4. 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.