# JAR/Class-file de-compilation reverse engineering and IP protection

Discussion in 'Java' started by Richard Maher, Sep 20, 2009.

1. ### Richard MaherGuest

Hi,

I appreciate that this has been discussed at length previously and there is
some useful stuff to be found on the net but can I please just ask someone
to confirm that there's not a whole lot one can do to stop an enthusiastic
(let alone dedicated) coder from converting a Java class file back to its
original source format?

My understanding (too strong a word here is that a custom class-loader
is probably the best bet but does anyone have a very simple example of one
of these, especially one that would not fall foul of the sandpit and other
requirements of an *unsigned* applet?

Are people routinely paying for "supported" obfuscators or rolling their
own? (And are they much of a deterrant and/or footprint-reduction impact in
the first place?)

Do you have examples of the quality of output one can produce from publicly
available de-compilers?

"All too hard", just rely on copyright protection and those companies who
might use it coughing up?

Cheers Richard Maher

Richard Maher, Sep 20, 2009

2. ### Joshua CranmerGuest

On 09/19/2009 08:19 PM, Richard Maher wrote:
> My understanding (too strong a word here is that a custom class-loader
> is probably the best bet but does anyone have a very simple example of one
> of these, especially one that would not fall foul of the sandpit and other
> requirements of an *unsigned* applet?

One method I have demonstrated (or rather, I first saw demonstrated), is
to replace java.lang.ClassLoader with a slightly modified version,
namely one that dumps the bytecodes out passed through the bottleneck
defineClass methods. I first saw this method online somewhere, but I
really have no clue as to how to find it.

And, of course, once you have the bytecode, you can run all the
decompilers and other tools you want on it as if it were a regular
classpath.

> Are people routinely paying for "supported" obfuscators or rolling their
> own? (And are they much of a deterrant and/or footprint-reduction impact in
> the first place?)

Obfuscation, insomuch as the names are turned into stuff like `a',
probably has a footprint-reduction impact, but I don't have hard numbers.

In terms of a deterrent, it would probably provide little to an
experienced hacker. Indeed, experienced hackers can easily crack the
copy protection on many new games or reverse engineer the license key
sections--and this is native code, which is theoretically much harder to
crack than bytecode. So fully reproducing readable source code, even in
full obfuscation mode, should only take a few hours for a moderately
complex class.

> "All too hard", just rely on copyright protection and those companies who
> might use it coughing up?

The best defense is to keep as much logic off the client side as
possible. Outside of that, all you'd do is slow down somewhat those who
would try to break it. Of course, if people do attempt that, that
generally means that you're program's successful enough to attract the
cracking community.

--
Beware of bugs in the above code; I have only proved it correct, not
tried it. -- Donald E. Knuth

Joshua Cranmer, Sep 20, 2009

3. ### Arne VajhøjGuest

Richard Maher wrote:
> I appreciate that this has been discussed at length previously and there is
> some useful stuff to be found on the net but can I please just ask someone
> to confirm that there's not a whole lot one can do to stop an enthusiastic
> (let alone dedicated) coder from converting a Java class file back to its
> original source format?
>
> My understanding (too strong a word here is that a custom class-loader
> is probably the best bet but does anyone have a very simple example of one
> of these, especially one that would not fall foul of the sandpit and other
> requirements of an *unsigned* applet?
>
> Are people routinely paying for "supported" obfuscators or rolling their
> own? (And are they much of a deterrant and/or footprint-reduction impact in
> the first place?)
>
> Do you have examples of the quality of output one can produce from publicly
> available de-compilers?
>
> "All too hard", just rely on copyright protection and those companies who
> might use it coughing up?

See below for an example.

I would not start messing around with a decrypting classloader.

Possible run an obfuscator like Proguard.

It ensure that the crackers actually have to do a little
bit of work.

And as a nice side effect it reduces the size of the
jar files a bit which is great for applets.

Arne

================================================

C:\>type Maher.java
public class Maher {
public static void main(String[] args) {
Richard r = new Richard();
r.dosomething();
}
}

class Richard {
public void dosomething() {
for(int i = 0; i < 3; i++) {
print();
}
}
private static void print() {
System.out.println("Ofuscation sucks");
}
}

C:\>javac Maher.java

C:\>java -cp . Maher
Ofuscation sucks
Ofuscation sucks
Ofuscation sucks

Parsing Maher.class...The class file version is 50.0 (only 45.3, 46.0
and 47.0 a
re supported)

// Decompiler options: packimports(3)
// Source File Name: Maher.java

public class Maher
{

public Maher()
{
}

public static void main(String args[])
{
Richard richard = new Richard();
richard.dosomething();
}
}

Parsing Richard.class...The class file version is 50.0 (only 45.3, 46.0
and 47.0
are supported)

// Decompiler options: packimports(3)
// Source File Name: Maher.java

import java.io.PrintStream;

class Richard
{

Richard()
{
}

public void dosomething()
{
for(int i = 0; i < 3; i++)
print();

}

private static void print()
{
System.out.println("Ofuscation sucks");
}
}

C:\>jar cvf rm.jar Maher.class Richard.class
adding: Maher.class(in = 317) (out= 241)(deflated 23%)
adding: Richard.class(in = 520) (out= 368)(deflated 29%)

C:\>java -cp rm.jar Maher
Ofuscation sucks
Ofuscation sucks
Ofuscation sucks

C:\>type rm.pro
-injars rm.jar
-outjars rmx.jar
-libraryjars <java.home>/lib/rt.jar

-keep public class Maher {
public static void main(java.lang.String[]);
}

C:\>java -jar proguard.jar @rm.pro
ProGuard, version 4.2
Preparing output jar [C:\rmx.jar]
Copying resources from program jar [C:\rm.jar]

C:\>java -cp rmx.jar Maher
Ofuscation sucks
Ofuscation sucks
Ofuscation sucks

C:\>jar xvf rmx.jar
inflated: META-INF/MANIFEST.MF
inflated: Maher.class
inflated: a.class

Parsing Maher.class...The class file version is 50.0 (only 45.3, 46.0
and 47.0 a
re supported)

// Decompiler options: packimports(3)

public class Maher
{

public Maher()
{
}

public static void main(String args[])
{
new a();
a.a();
}
}

Parsing a.class...The class file version is 50.0 (only 45.3, 46.0 and
47.0 are s
upported)

// Decompiler options: packimports(3)

import java.io.PrintStream;

final class a
{

a()
{
}

public static void a()
{
for(int i = 0; i < 3; i++)
System.out.println("Ofuscation sucks");

}
}

C:\>

Arne Vajhøj, Sep 20, 2009
4. ### Richard MaherGuest

Hi Arne,

"Arne Vajhøj" <> wrote in message
news:4ab581d9$0$293$... Wrote lots of good stuff with examples (see below for details) Thanks very much for the great info and examples! That JAD looks pretty scary! Even preserves/provides indentation. Source-code on demand - How easy was that :-( I do like the look of that Proguard though (especially being able to "keep" the Applet or Main class) so I will read up on it (licensing etc). I guess one downside of this method is having to re-test all your code after it's been PROGUARDed. (Or don't deploy it to test until it's been PROGUARDed I suppose?) Then there's the support issue and "How long, after a new version of Java, is it before Proguard has a version that supports it?". But that's any software/freeware I guess, and if your deliberately using old Java versions then what does it matter? Still, it also shrinks the JAR size down then this could well be worth persuing - Thanks again! Cheers Richard Maher PS. I'll read the website testimonials, but if anyone here has had bad experiences then please let me know. "Arne Vajhøj" <> wrote in message news:4ab581d9$0$293$...
> Richard Maher wrote:
> > I appreciate that this has been discussed at length previously and there

is
> > some useful stuff to be found on the net but can I please just ask

someone
> > to confirm that there's not a whole lot one can do to stop an

enthusiastic
> > (let alone dedicated) coder from converting a Java class file back to

its
> > original source format?
> >
> > My understanding (too strong a word here is that a custom

> > is probably the best bet but does anyone have a very simple example of

one
> > of these, especially one that would not fall foul of the sandpit and

other
> > requirements of an *unsigned* applet?
> >
> > Are people routinely paying for "supported" obfuscators or rolling their
> > own? (And are they much of a deterrant and/or footprint-reduction impact

in
> > the first place?)
> >
> > Do you have examples of the quality of output one can produce from

publicly
> > available de-compilers?
> >
> > "All too hard", just rely on copyright protection and those companies

who
> > might use it coughing up?

>
> See below for an example.
>
> I would not start messing around with a decrypting classloader.
>
> Possible run an obfuscator like Proguard.
>
> It ensure that the crackers actually have to do a little
> bit of work.
>
> And as a nice side effect it reduces the size of the
> jar files a bit which is great for applets.
>
> Arne
>
> ================================================
>
> C:\>type Maher.java
> public class Maher {
> public static void main(String[] args) {
> Richard r = new Richard();
> r.dosomething();
> }
> }
>
> class Richard {
> public void dosomething() {
> for(int i = 0; i < 3; i++) {
> print();
> }
> }
> private static void print() {
> System.out.println("Ofuscation sucks");
> }
> }
>
> C:\>javac Maher.java
>
> C:\>java -cp . Maher
> Ofuscation sucks
> Ofuscation sucks
> Ofuscation sucks
>
> Parsing Maher.class...The class file version is 50.0 (only 45.3, 46.0
> and 47.0 a
> re supported)
>
> // Decompiler options: packimports(3)
> // Source File Name: Maher.java
>
>
> public class Maher
> {
>
> public Maher()
> {
> }
>
> public static void main(String args[])
> {
> Richard richard = new Richard();
> richard.dosomething();
> }
> }
>
> Parsing Richard.class...The class file version is 50.0 (only 45.3, 46.0
> and 47.0
> are supported)
>
> // Decompiler options: packimports(3)
> // Source File Name: Maher.java
>
> import java.io.PrintStream;
>
> class Richard
> {
>
> Richard()
> {
> }
>
> public void dosomething()
> {
> for(int i = 0; i < 3; i++)
> print();
>
> }
>
> private static void print()
> {
> System.out.println("Ofuscation sucks");
> }
> }
>
> C:\>jar cvf rm.jar Maher.class Richard.class
> adding: Maher.class(in = 317) (out= 241)(deflated 23%)
> adding: Richard.class(in = 520) (out= 368)(deflated 29%)
>
> C:\>java -cp rm.jar Maher
> Ofuscation sucks
> Ofuscation sucks
> Ofuscation sucks
>
> C:\>type rm.pro
> -injars rm.jar
> -outjars rmx.jar
> -libraryjars <java.home>/lib/rt.jar
>
> -keep public class Maher {
> public static void main(java.lang.String[]);
> }
>
> C:\>java -jar proguard.jar @rm.pro
> ProGuard, version 4.2
> Preparing output jar [C:\rmx.jar]
> Copying resources from program jar [C:\rm.jar]
>
> C:\>java -cp rmx.jar Maher
> Ofuscation sucks
> Ofuscation sucks
> Ofuscation sucks
>
> C:\>jar xvf rmx.jar
> inflated: META-INF/MANIFEST.MF
> inflated: Maher.class
> inflated: a.class
>
> Parsing Maher.class...The class file version is 50.0 (only 45.3, 46.0
> and 47.0 a
> re supported)
>
> // Decompiler options: packimports(3)
>
>
> public class Maher
> {
>
> public Maher()
> {
> }
>
> public static void main(String args[])
> {
> new a();
> a.a();
> }
> }
>
> Parsing a.class...The class file version is 50.0 (only 45.3, 46.0 and
> 47.0 are s
> upported)
>
> // Decompiler options: packimports(3)
>
> import java.io.PrintStream;
>
> final class a
> {
>
> a()
> {
> }
>
> public static void a()
> {
> for(int i = 0; i < 3; i++)
> System.out.println("Ofuscation sucks");
>
> }
> }
>
> C:\>
>

Richard Maher, Sep 20, 2009
5. ### Qu0llGuest

"Richard Maher" <> wrote in message
news:h944js$hkr$...

[...]

> I do like the look of that Proguard though (especially being able to
> "keep"
> the Applet or Main class) so I will read up on it (licensing etc).
>
> I guess one downside of this method is having to re-test all your code
> after
> it's been PROGUARDed. (Or don't deploy it to test until it's been
> PROGUARDed
> I suppose?) Then there's the support issue and "How long, after a new
> version of Java, is it before Proguard has a version that supports it?".
> But
> that's any software/freeware I guess, and if your deliberately using old
> Java versions then what does it matter?
>
> Still, it also shrinks the JAR size down then this could well be worth
> persuing - Thanks again!
>
> Cheers Richard Maher
>
> experiences then please let me know.

My Java development focuses on applets and I simply could not imagine life
without ProGuard. It's an awesome tool and I rely on it heavily. So far it
has proven to be extremely safe and only occasionally have I encountered any
kind of issue with it and, even then, Eric Lafortune whom maintains it has
been quick to patch to fix. You'll find it removes heaps of dead code you

Yes, you certainly do need to re-test your code because there are some
things that will be removed when you don't want them to be or some things
which relied on non-obfuscated class names etc. but all of these things can
be fixed by correct configuration. ProGuard even optimises your code so it
will run faster!

Anyway Eric, you have my email address, I will be expecting a small reward
for this otherwise unpaid endorsement!

--
And loving it,

-Qu0ll (Rare, not extinct)
_________________________________________________

[Replace the "SixFour" with numbers to email me]

Qu0ll, Sep 20, 2009
6. ### Roedy GreenGuest

On Sun, 20 Sep 2009 08:19:58 +0800, "Richard Maher"
<> wrote, quoted or indirectly quoted
someone who said :

>I appreciate that this has been discussed at length previously and there is
>some useful stuff to be found on the net but can I please just ask someone
>to confirm that there's not a whole lot one can do to stop an enthusiastic
>(let alone dedicated) coder from converting a Java class file back to its
>original source format?

See http://mindprod.com/jgloss/obfuscator.html
http://mindprod.com/jgloss/decompiler.html
http://mindprod.com/jgloss/disassembler.html

You are right, it is very easy to decompile/disassemble a source file.

Most of the time you flatter yourself if you think any one module
contains some great secret. It is only the app as a whole you want to
discourage from piracy.

The most serious approach is native optimised compilation. See
http://mindprod.com/jgloss/nativecompiler.html

My own preferred approach needs an Internet connection, frequent
running small parts of the app on a server where the hacker can't even
look at them.
--
http://mindprod.com

"Perfect reusable components are not obtained at the first shot."
~ Bertrand Meyer (born: 1950 age: 59) 1989, creator of design by contract and the Eiffel language.

Roedy Green, Sep 20, 2009
7. ### Joshua CranmerGuest

On 09/19/2009 10:42 PM, Richard Maher wrote:
> That JAD looks pretty scary! Even preserves/provides indentation.
> Source-code on demand - How easy was that :-(

The last I checked, JAD could not decompile the Java 5-specific stuff.
In fact, to my knowledge, only one fully-functioning decompiler exists
that can do it.

--
Beware of bugs in the above code; I have only proved it correct, not
tried it. -- Donald E. Knuth

Joshua Cranmer, Sep 20, 2009
8. ### Arne VajhøjGuest

Richard Maher wrote:
> "Arne Vajhøj" <> wrote in message
> news:4ab581d9$0$293$... > Wrote lots of good stuff with examples (see below for details) > > Thanks very much for the great info and examples! > > That JAD looks pretty scary! Even preserves/provides indentation. > Source-code on demand - How easy was that :-( It does not preserve, but it tries to write the code as readable as possible. > I do like the look of that Proguard though (especially being able to "keep" > the Applet or Main class) so I will read up on it (licensing etc). ProGuard is GPL with some exceptions. But they explicit state that it does not have any impact on the input or output code. http://proguard.sourceforge.net/license.html ProGuard is free. You can use it freely for processing your applications, commercial or not. Your code obviously remains yours after having been processed, and its license can remain the same. > I guess one downside of this method is having to re-test all your code after > it's been PROGUARDed. (Or don't deploy it to test until it's been PROGUARDed > I suppose?) Yes. > Then there's the support issue and "How long, after a new > version of Java, is it before Proguard has a version that supports it?". But > that's any software/freeware I guess, and if your deliberately using old > Java versions then what does it matter? If you study the download section at: http://sourceforge.net/projects/proguard/files/ then it seems rather actively maintained. Obviously no guarantee for the future. Arne Arne Vajhøj, Sep 20, 2009 9. ### Roedy GreenGuest On Sun, 20 Sep 2009 08:09:55 -0400, Joshua Cranmer <> wrote, quoted or indirectly quoted someone who said : >The last I checked, JAD could not decompile the Java 5-specific stuff. >In fact, to my knowledge, only one fully-functioning decompiler exists >that can do it. It decompiles it, but not into idiomatic java with enums and generics. However, if all you want to do is figure out how the program works, it tell you all you need to know. I have some sample decompiles posted at http://mindprod.com/jgloss/enum.html They helped me figure out how enums worked under the hood. -- Roedy Green Canadian Mind Products http://mindprod.com "Perfect reusable components are not obtained at the first shot." ~ Bertrand Meyer (born: 1950 age: 59) 1989, creator of design by contract and the Eiffel language. Roedy Green, Sep 20, 2009 10. ### Roedy GreenGuest On Sun, 20 Sep 2009 08:24:18 -0400, Arne Vajhøj <> wrote, quoted or indirectly quoted someone who said : >> That JAD looks pretty scary! Even preserves/provides indentation. >> Source-code on demand - How easy was that :-( > >It does not preserve, but it tries to write the code as readable as >possible. Indentation and local variable names are not normally included in the class files. However, a decompiler can reconstruct them with quite plausible code. For example, a local variable of the Sample class it can call "sample". -- Roedy Green Canadian Mind Products http://mindprod.com "Perfect reusable components are not obtained at the first shot." ~ Bertrand Meyer (born: 1950 age: 59) 1989, creator of design by contract and the Eiffel language. Roedy Green, Sep 20, 2009 11. ### Mike AmlingGuest Qu0ll wrote: > My Java development focuses on applets and I simply could not imagine > life without ProGuard. It's an awesome tool and I rely on it heavily. > So far it has proven to be extremely safe and only occasionally have I > encountered any kind of issue with it and, even then, Eric Lafortune > whom maintains it has been quick to patch to fix. You'll find it > removes heaps of dead code you never knew you had and shrink your applet > considerably. > > Yes, you certainly do need to re-test your code because there are some > things that will be removed when you don't want them to be or some > things which relied on non-obfuscated class names etc. but all of these > things can be fixed by correct configuration. ProGuard even optimises > your code so it will run faster! The last time I tested ProGuard, and it has been a while, it caused this construct class Foo { static final String CLASS_NAME=Foo.class.getName(); } to fail after Foo was renamed. It looks like "Foo.class" uses a String literal that ProGuard did not alter to the new name. Any idea if that's still broken? I will admit that static final String CLASS_NAME=new Foo().getClass().getName(); does work even after ProGuard renames Foo. --Mike Amling Mike Amling, Sep 20, 2009 12. ### Joshua CranmerGuest On 09/20/2009 09:15 AM, Mike Amling wrote: > The last time I tested ProGuard, and it has been a while, it caused this > construct > > class Foo { > static final String CLASS_NAME=Foo.class.getName(); > } > > to fail after Foo was renamed. It looks like "Foo.class" uses a String > literal that ProGuard did not alter to the new name. Any idea if that's > still broken? Java 5 and later directly uses a ldc on the class item from the constant pool for class literals, instead of the synthetic check-and-set. If ProGuard is merely changing the names in the constant pool, it shouldn't break with any code compiled (and targeted!) with Java 5 or newer compilers. -- Beware of bugs in the above code; I have only proved it correct, not tried it. -- Donald E. Knuth Joshua Cranmer, Sep 20, 2009 13. ### Richard MaherGuest Hi Qu0ll, "Qu0ll" <> wrote in message news:4ab5c5d7$0$10337$...
> My Java development focuses on applets and I simply could not imagine life
> without ProGuard.

But how did you go with your previously declared home-grown Logger utility
and the, now induced, inability to interrogate the Stack for caller class id
and line-number etc? Would it not be defeating the purposes of the
obfuscation to introduce code that passes around the "real" class-names to

Do you still have logging/verbosity levels that perhaps include DEBUG? Or is
it a simple case of System.out.println("Doh! called from " +
appletWideUniqueErrorId)

> It's an awesome tool and I rely on it heavily. So far it
> has proven to be extremely safe and only occasionally have I encountered

any
> kind of issue with it and, even then, Eric Lafortune whom maintains it has
> been quick to patch to fix. You'll find it removes heaps of dead code you

Sounds great.

>
> Yes, you certainly do need to re-test your code because there are some
> things that will be removed when you don't want them to be or some things
> which relied on non-obfuscated class names etc. but all of these things

can
> be fixed by correct configuration. ProGuard even optimises your code so

it
> will run faster!

It would be churlish to not at least give it a try

Cheers Richard Maher

Richard Maher, Sep 21, 2009
14. ### Richard MaherGuest

Hi Roedy,

"Roedy Green" <> wrote in message
news:...
> On Sun, 20 Sep 2009 08:19:58 +0800, "Richard Maher"
> <> wrote, quoted or indirectly quoted
> someone who said :
>
> >I appreciate that this has been discussed at length previously and there

is
> >some useful stuff to be found on the net but can I please just ask

someone
> >to confirm that there's not a whole lot one can do to stop an

enthusiastic
> >(let alone dedicated) coder from converting a Java class file back to its
> >original source format?

>
> See http://mindprod.com/jgloss/obfuscator.html
> http://mindprod.com/jgloss/decompiler.html
> http://mindprod.com/jgloss/disassembler.html

(Well done with the Java service you're providing btw)
>
> You are right, it is very easy to decompile/disassemble a source file.
>
> Most of the time you flatter yourself if you think any one module
> contains some great secret. It is only the app as a whole you want to
> discourage from piracy.

You're probably right, and it wouldn't be the first time I was found-out
flattering myself, but what the code does certainly impresses the hell out
of me! Add to that the fact that there's *nothing* out there doing the same
thing, as well as my heart-flet desire to delay the HTTP hordes from trying
to stuff yet another huge, ugly, replicant of a pig's-ear into the glass
slipper and, hey, it's worth a shot.
>
> The most serious approach is native optimised compilation. See
> http://mindprod.com/jgloss/nativecompiler.html
>
> My own preferred approach needs an Internet connection, frequent
> downloads of crucial pieces of code, with sanity checks, or even
> running small parts of the app on a server where the hacker can't even
> look at them.
> --
> Roedy Green Canadian Mind Products

Cheers Richard Maher

Richard Maher, Sep 21, 2009
15. ### Qu0llGuest

Hi Richard,

> But how did you go with your previously declared home-grown Logger utility
> and the, now induced, inability to interrogate the Stack for caller class
> id
> and line-number etc? Would it not be defeating the purposes of the
> obfuscation to introduce code that passes around the "real" class-names to
>
> Do you still have logging/verbosity levels that perhaps include DEBUG? Or
> is
> it a simple case of System.out.println("Doh! called from " +
> appletWideUniqueErrorId)

I haven't been using logging which identifies the class name and line of
code beyond the debugging stage i.e. I only use it before using ProGuard.
After that my logging framework simply displays informative messages with a
timestamp and thread information which is still very useful. It is still
possible to determine the class name in the logging but it will be the
obfuscated class name.

ProGuard has a retrace facility that allows you to decode obfuscated stack
traces and convert them into their original class names and line numbers.

--
And loving it,

-Qu0ll (Rare, not extinct)
_________________________________________________

[Replace the "SixFour" with numbers to email me]

Qu0ll, Sep 21, 2009
16. ### GilbertGuest

Joshua Cranmer wrote:

> On 09/19/2009 08:19 PM, Richard Maher wrote:
>> My understanding (too strong a word here is that a custom
>> class-loader is probably the best bet but does anyone have a very simple
>> example of one of these, especially one that would not fall foul of the
>> sandpit and other requirements of an *unsigned* applet?

>
> One method I have demonstrated (or rather, I first saw demonstrated), is
> to replace java.lang.ClassLoader with a slightly modified version,
> namely one that dumps the bytecodes out passed through the bottleneck
> defineClass methods. I first saw this method online somewhere, but I
> really have no clue as to how to find it.
>
> And, of course, once you have the bytecode, you can run all the
> decompilers and other tools you want on it as if it were a regular
> classpath.
>

file with a random byte(s) on the end, and then use a custom class loader
that drops the last byte(s) when reading the bytecode.

Regards

Gilbert, Sep 21, 2009
17. ### Joshua CranmerGuest

On 09/21/2009 01:45 PM, Gilbert wrote:
> file with a random byte(s) on the end, and then use a custom class loader
> that drops the last byte(s) when reading the bytecode.

That still won't defeat the method I describe. Essentially, it captures
the bytecode at the level where the information is passed from the Java
methods to the native definition. I think even if you use JNI, it's
/still/ captured at that point, so there is no way to have Java run on
anything other than your own custom VM and still avoid being captured at
that point.

--
Beware of bugs in the above code; I have only proved it correct, not
tried it. -- Donald E. Knuth

Joshua Cranmer, Sep 21, 2009