The meaning of the class file on the file system

I am learning lambda expressions, the book illustrates an example that uses the toString()

lambda expression method .

Supplier<ArrayList<String>> s1 = ArrayList<String>::new;
ArrayList<String> a1 = s1.get();
System.out.println(s1);
//Output: functionalinterface.BuiltIns$$Lambda$1/791452441@1fb3ebeb

      

He explains the meaning of the inference as,

It really means something. Our test class is named BuiltIns, and it's in a package we created called functionalinterface. Then comes $$

what means the class does not exist in the class file on the filesystem. It only exists in memory.

I don't understand the meaning of the last sentences. Could you express it?

Source: OCP: Java SE 8 Software Tutorial, Java SE 8 Certified, Zhanna Boyarski, Scott Selikov

+3


source to share


3 answers


Ok, the book is a little misleading. This statement is indeed true, but with minor correction. It assumes that if you have $

a class name in it, it is automatically created (not by you); which cannot be a fact.

For example, suppose this example:

public class TestSO {

   public static void main(String[] args) {
      Test t = new Test() {
      };
   }

   static class Test {}
}

      

You have created an anonymous inner class, which is actually a simple compiler-generated class. If you compile TestSO

, you will see a named class TestSO\$1.class

that was generated for you. If you check what it looks like with help javap -c -p TestSO\$1.class

, you will see something like this:

final class TestSO$1 extends TestSO$Test { ... 

      

But at the same time, it is perfectly legal for you to declare a class / method that contains a symbol $

:

static class $$Test2$$ {}

      

Thus, the presence is $$

not a conclusive indication that the class is being generated by the compiler / runtime. Also, an implementation detail that might change some day ...

Now at the same time, the book is correct in that the class doesn’t exist in a class file on the file system. It exists only in memory

.

Supplier

is an interface, and you haven't provided a class that implements it, have you? Ok, what's going on next, interesting.

I'm not going to go into details, but here's a simplified explanation.



If you decompile your example ( javap -p -c -v TestSO.class

) you will see a line like this:

invokedynamic #2,  0  // InvokeDynamic #0:get:()Ljava/util/function/Supplier;

      

Which invokedynamic

does letting you runtime

decide how to provide an actual instance of this Supplier

. And at runtime there is an actual class created that implements this Supplier

one that is being used.

You can see what this class looks like with the command used when it runs:

-Djdk.internal.lambda.dumpProxyClasses=/Your/Path/Here

      

As a result, along the way, you will see a class named:

TestSO$$Lambda$1.class 

      

And again if you decompile it with javap -c -p TestSO\$\$Lambda\$1.class

:

 final class TestSO$$Lambda$1 
         implements java.util.function.Supplier {....

      

What the author is trying to say is that at runtime there will be created class

one that implements the provider interface, but not the one who created it.

+3


source


This example is an attempt to explain something in simpler or more colloquial language, avoiding too formal, but the result can be called disastrous.

The name actually means nothing. The class of the instance provided for the lambda expression or method reference is intentionally undefined and that is its name. It is not even specified whether a method toString()

that is implicitly called at runtime System.out.println(s1);

will output the output of "classname @hashcode".



Whether filesystems are affected or not is irrelevant. The correct and factual point is that the class of this instance is not among the classes generated by the Java compiler when your application is compiled. Instead, it is provided by the JRE at runtime in a specific way. OpenJDK provides a generated class that has a name that contains the class that contains the lambda expression and $$

, but as said, is an implementation detail. And as Eugene explains , the dollar sign is a legal part of Java identifiers, so having two dollar signs does not prove a specific property.

+2


source


When you create a class, you inject a file .java

and compile it to .class

. Both are actual files that exist somewhere on your filesystem. $$

shows that it is different. No .java class

on file system. Instead, Java creates a class for us. This way you don't need to inject a class and can just provide a lambda expression.

Its author Ms Boyarsky answers

+1


source







All Articles