Let me start with a little java test.

The following code prints “Hi, There”

Can you explain how it does that ?

public class Test {

public static void main(String args[]) {

try {

new ClassLoader() {

public Class<?> findClass(String c) {

byte[] bytecode = java.util.Base64.getDecoder().decode(

"yv66vgAAADQAGAoABgAKCQALAAwIAA0KAA4ADwcAEAcAEQEABjxpb"+

"l0PgEAAygpVgEABENvZGUMAAcACAcAEgwAEwAUAQAJSGksIHRoZXJ"+

"lBwAVDAAWABcBAAFBAQAQamF2YS9sYW5nL09iamVjdAEAEGphdmEv"+

"bGFuZy9TeXN0ZW0BAANvdXQBABVMamF2YS9pby9QcmludFN0cmVhb"+

"TsBABNqYXZhL2lvL1ByaW50U3RyZWFtAQAHcHJpbnRsbgEAFShMam"+

"F2YS9sYW5nL1N0cmluZzspVgAhAAUABgAAAAAAAQABAAcACAABAAk"+

"AAAAZAAIAAQAAAA0qtwABsgACEgO2AASxAAAAAAAA");

return defineClass(“A”, bytecode, 0, bytecode.length);

}

}.loadClass(“A”).newInstance();

} catch (Exception e) {

throw new RuntimeException(e);

}

}

}

The answer is:

It does so by creating a new class A and by instantiating it. Of course, Class A looks something like this:

public class A {

public A() {

System.out.println(“Hi, there”);

}

}

although, regrettably, in Test.java you cannot really see much of its code.

It is however there, presented in its raw format (bytecode) encoded in a base64 string.

If you wonder, the string representation for A as it appears in Test.java can be generated by compiling A.java and then accessing like this:

URL url = A.class.getResource("A.class");

byte array[] = Files.readAllBytes(Paths.get(url.toURI()));

String bytecode = Base64.getEncoder().encodeToString(array);

System.out.println(bytecode); // this prints yv66vgAAADQAGAoAB…

What’s the point ?

So, aside from making our code impossible to read (which is very bad), is there any benefit in dealing with raw bytecode like this ?



Well, since you can encode bytecode into a piece of code you can now take a different approach on distributing your work and ask people to copy and paste a snippet of code inside their java program instead of downloading a jar.

Surely, this approach is not for everybody but it might be worthwhile in a few cases:

“try-before-you-use” demos Some specialised solutions where:

- Your library is ultra light and has no dependencies (or only dependencies you can assume being present in the environment when it gets integrated)

- Your API is minimal.

- Your tool’s service is purely additive (such as is the case for monitoring apps, profilers, coverage analyzers, event loggers, etc. ).

A real example

I have used this approach in nudge4j.

nudge4j is a monitoring tool for java applications which is typically used during development.

A copy/paste approach to me seemed ideal.

Thanks for reading this.