Okay, everybody who touches Java bytecode

The Oracle v. Google holds that copying the Structure, Sequence, and Organization of the Java APIs is a copyright violation. And a copyright violation is not just the act of copying, but also applies to all the intermediate parties that have a copy of the work.

That's anybody who writes/compiles any JVM language and anyone who has a JAR file on any device they posses... including a Java ME applet on your old Motorola flip phone. In fact, the JVM in all its incarnations is so pervasive, it's likely that every adult in every industrialized nation has some JVM running someplace.

And every non-Sun/Oracle JAR files has a copy of some or all of the Java API embedded in it because it's technically necessary to include a shadow of the API in compiled bytecode in order to invoke the API.

Let me demonstrate.

Here's a perfectly legal Java program that I wrote and I own the copyright to:

public class HelloWorld {

    public static void main(String[] args) {
	int strlen = 0;

	for (int x = 0; x < args.length; x++) {
	    strlen += args[x].length();

	System.out.println("Hello, world, you passed in "+args.length+" arguments, "+
			   "total size: "+strlen);


Nothing in there looks infringing. I run the program through the OpenJDK Java compiler, javac which results in a HelloWorld.class file. According to how the industry has used Java and compilers in general, the resulting bytecode is a derivative work of the source code and I own the copyright in the source code.

So, let's take a look at the resulting bytecode, disassembled with javap:

dpp@crown:~/proj/dpp-blog/images$ javap -c HelloWorld
Compiled from "HelloWorld.java"
public class HelloWorld {
  public HelloWorld();
       0: aload_0       
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return        

  public static void main(java.lang.String[]);
       0: iconst_0      
       1: istore_1      
       2: iconst_0      
       3: istore_2      
       4: iload_2       
       5: aload_0       
       6: arraylength   
       7: if_icmpge     25
      10: iload_1       
      11: aload_0       
      12: iload_2       
      13: aaload        
      14: invokevirtual #2                  // Method java/lang/String.length:()I
      17: iadd          
      18: istore_1      
      19: iinc          2, 1
      22: goto          4
      25: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
      28: new           #4                  // class java/lang/StringBuilder
      31: dup           
      32: invokespecial #5                  // Method java/lang/StringBuilder."<init>":()V
      35: ldc           #6                  // String Hello, world, you passed in 
      37: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      40: aload_0       
      41: arraylength   
      42: invokevirtual #8                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      45: ldc           #9                  // String  arguments, 
      47: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      50: ldc           #10                 // String total size: 
      52: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      55: iload_1       
      56: invokevirtual #8                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      59: invokevirtual #11                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      62: invokevirtual #12                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      65: return        

Oh my... look, some of the Java APIs snuck right into the code.

In fact, the JVM requires the call site (the place where code is called) to include information about the API that's being called in order for the JVM to figure out the method to be called. And not just the method name, but also the parameter types passed in and the expected return type.

So each and every compiled JAR contains some part of the Java API embedded in it. Each and every compiled JAR file is a copyright violation under the Oracle decision.

"But," you say, "the JAR file doesn't contain all of the disputed API."

First, how much is enough. The Oracle court explicitly rejected the argument that the APIs were a small part of the overall work of the Java base classes and that percentage arguments were not persuasive.

Second, for repositories like Maven Central that house tens of thousands of JAR files, substantially all of the Java APIs are copied into the collective works that are housed in those JAR files.

What to do?

If I were hosting a ton of JAR files, I'd be on the phone to my lawyers trying to figure out what to do. Yeah, maybe there's an inducement argument because Oracle distributes javac and therefore is inducing me to copy the Java APIs. But still, it's a technical violation of the Oracle court's decision.

If I were the Apache Software Foundation or the Free Software Foundation, I'd be filing an ex parte motion this morning to get a stay of the Oracle decision because it means that what we've been thinking is our software that we can license on our open terms in fact contains Oracle copyrighted code and we will have to suspend all of our JVM-related open source projects.

Oh, and I should point out that if Oracle claims that the APIs copied into the JAR files are not covered by copyright, then all Google has to do is pull all the JAR files from Maven Central, find all the Java API references in all those JAR files and use that information to declare an API for Android. That's about 10 man-days of effort, at most.