Question

Recently I came across a query while reading THE STRUCTURE OF THE JAVA VIRTUAL MACHINE

On page no-5 ch. 2,

Compiled code to be executed by the Java Virtual Machine is represented using a hardware- and operating system-independent binary format, typically (but not necessarily) stored in a file, known as the class file format.

That bracket But not necessarily is the reason.

Question is,

In which case compiled code will not be stored in class file ? and if it will not be stored in class file, then where and how ?

Edit : Please note that question is not about ClassLoader.

Was it helpful?

Solution

You seem more interest in how to generate a java class file in memory so here goes:

public class CompileSourceInMemory {
    public static void main(String args[]) throws IOException {
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        DiagnosticCollector<JavaFileObject> diagnostics = new    DiagnosticCollector<JavaFileObject>();

        StringWriter writer = new StringWriter();
        PrintWriter out = new PrintWriter(writer);
        out.println("public class HelloWorld {");
        out.println("  public static void main(String args[]) {");
        out.println("    System.out.println(\"This is in another java file\");");    
        out.println("  }");
        out.println("}");
        out.close();
        JavaFileObject file = new JavaSourceFromString("HelloWorld", writer.toString());

        Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(file);
        CompilationTask task = compiler.getTask(null, null, diagnostics, null, null, compilationUnits);

        boolean success = task.call();

        if (success) {
            try {
                Class.forName("HelloWorld").getDeclaredMethod("main", new Class[] { String[].class }).invoke(null, new Object[] { null });
            } catch (ClassNotFoundException e) {
                System.err.println("Class not found: " + e);
            } catch (NoSuchMethodException e) {
                System.err.println("No such method: " + e);
            } catch (IllegalAccessException e) {
                System.err.println("Illegal access: " + e);
            } catch (InvocationTargetException e) {
                System.err.println("Invocation target: " + e);
            }
        }
    }
}

class JavaSourceFromString extends SimpleJavaFileObject {
    final String code;

    JavaSourceFromString(String name, String code) {
        super(URI.create("string:///" + name.replace('.','/') + Kind.SOURCE.extension),Kind.SOURCE);
        this.code = code;
    }

    @Override
    public CharSequence getCharContent(boolean ignoreEncodingErrors) {
        return code;
    }
}

Source: In memory compilation

This generates a class in memory without any external representation of the java source or compiled class.

OTHER TIPS

In java, where a classloader gets the binary compiled from depends on it's implementation. It's possible to write a class loader that loads it's classes from a database, from the net, from memory or any other thinkable location.

The default java URLClassLoader uses files in directories or jars, so that's where the "typically" comes from, the "not necessarily" is just a hint that there may be other implementations.

Storing compiled code in a .class file is only the standard and more convenient way of getting executable code for a JVM, however, the same compiled code can be obtained from many other sources, it could be obtained as a text or binary stream from a DB or from a network connection or from memory at runtime, check this example or this one

Yes, this question is about Classloader!

The Classloader is the (only) way the JVM brings in classes. The classes could be in files, JAR archives, somewhere on the network, in a database blob, in shared memory, on paper tape (if your machine has a paper tape reader) or they could even be generated on the fly.

So, this is the answer to your question.

The standard compiler uses to write class files, but, as Peter commented, this is not necessarily so. And, above all, just because the javac command writes class files that does not mean we must use those files. It is common to pack them in a JAR, and use that instead.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top