Add jep512 module: compact source files and instance main methods on JDK 25 and 27
Runnable sources, broken examples and captured transcripts for the ankurm.com JEP 512 article, including the measured launch order and a private-constructor difference between 25 and 27. Co-Authored-By: Claude Sonnet 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01TF9JWFvJSNm6HVzswzZU5a
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
$ cat src/Hello.java
|
||||
// The smallest complete Java 25 program. No class, no public, no static, no String[] args.
|
||||
void main() {
|
||||
IO.println("Hello, world");
|
||||
}
|
||||
|
||||
$ java src/Hello.java (JDK 25: OpenJDK Runtime Environment Temurin-25.0.4.1+1 (build 25.0.4.1+1-LTS))
|
||||
Hello, world
|
||||
|
||||
$ java src/Hello.java (JDK 27: OpenJDK Runtime Environment Temurin-27+35 (build 27+35))
|
||||
Hello, world
|
||||
|
||||
$ ls src/*.class
|
||||
ls: cannot access 'src/*.class': No such file or directory
|
||||
|
||||
$ java src/Hello.java (JDK 21: OpenJDK Runtime Environment (build 21.0.10+7-Ubuntu-124.04))
|
||||
src/Hello.java:2: error: unnamed classes are a preview feature and are disabled by default.
|
||||
void main() {
|
||||
^
|
||||
(use --enable-preview to enable unnamed classes)
|
||||
1 error
|
||||
error: compilation failed
|
||||
@@ -0,0 +1,22 @@
|
||||
$ javac -d out src/Hello.java && java -cp out Hello
|
||||
Hello, world
|
||||
|
||||
$ javap -p -cp out Hello
|
||||
Compiled from "Hello.java"
|
||||
final class Hello {
|
||||
Hello();
|
||||
void main();
|
||||
}
|
||||
|
||||
$ javap -v -cp out Hello | grep -E 'major|flags'
|
||||
major version: 69
|
||||
flags: (0x0030) ACC_FINAL, ACC_SUPER
|
||||
|
||||
$ java Reflect (asks the loaded class)
|
||||
name : Hello
|
||||
final : true
|
||||
public : false
|
||||
package : '' (unnamed)
|
||||
superclass : java.lang.Object
|
||||
declared : [void Hello.main()]
|
||||
constructors: [Hello()]
|
||||
@@ -0,0 +1,25 @@
|
||||
$ java src/Members.java
|
||||
HELLO!
|
||||
apple, banana, cherry
|
||||
{apple=5, banana=6, cherry=6}
|
||||
2.10
|
||||
Point[x=3, y=4] is 5.0 from the origin
|
||||
calls so far: 1
|
||||
|
||||
$ java src/WithArgs.java one two
|
||||
args.length = 2
|
||||
arg: one
|
||||
arg: two
|
||||
|
||||
$ java src/InstanceMainInClass.java
|
||||
hello from an instance field
|
||||
this class is InstanceMainInClass, final? false
|
||||
|
||||
$ java src/NeedsImport.java (java.net.http is outside java.base: a normal import fixes it)
|
||||
default HTTP version: HTTP_2
|
||||
|
||||
$ java src/NeedsModuleImport.java (or import the whole module)
|
||||
default HTTP version: HTTP_2
|
||||
|
||||
$ java multi/App.java (App.java + Greeter.java in one directory)
|
||||
Hello, multi-file source launcher (from a second file)
|
||||
@@ -0,0 +1,22 @@
|
||||
$ printf 'Ankur\n30\n' | java src/ReadLn.java
|
||||
Your name? Your age? Hello Ankur, 30 is a good age to learn Java.
|
||||
no newline after this, newline after this
|
||||
|
||||
$ java src/IoInAnyClass.java
|
||||
IO.println works in a normal class with no import
|
||||
|
||||
$ java src/StaticImportIO.java (import static java.lang.IO.* makes the bare form work)
|
||||
println without the IO. prefix, after import static java.lang.IO.*
|
||||
|
||||
$ java broken/NoIoPrefix.java (JDK 27: same error as on 25)
|
||||
broken/NoIoPrefix.java:2: error: cannot find symbol
|
||||
println("hello");
|
||||
^
|
||||
symbol: method println(String)
|
||||
location: class NoIoPrefix
|
||||
1 error
|
||||
error: compilation failed
|
||||
|
||||
$ printf '' | java src/ReadLn.java (stdin closed: what does readln return?)
|
||||
Your name? Your age? Hello null, null is a good age to learn Java.
|
||||
no newline after this, newline after this
|
||||
@@ -0,0 +1,22 @@
|
||||
== OpenJDK Runtime Environment Temurin-25.0.4.1+1 (build 25.0.4.1+1-LTS)
|
||||
SS_i0 declares: static void main(String[] a) void main() -> ran: static main(String[])
|
||||
S0_iS declares: static void main() void main(String[] a) -> ran: instance main(String[])
|
||||
SS_S0 declares: static void main(String[] a) static void main() -> ran: static main(String[])
|
||||
IS_I0 declares: void main(String[] a) void main() -> ran: instance main(String[])
|
||||
-- same four classes, compiled first and launched as a class (java -cp out NAME)
|
||||
SS_i0 -> ran: static main(String[])
|
||||
S0_iS -> ran: instance main(String[])
|
||||
SS_S0 -> ran: static main(String[])
|
||||
IS_I0 -> ran: instance main(String[])
|
||||
|
||||
== OpenJDK Runtime Environment Temurin-27+35 (build 27+35)
|
||||
SS_i0 declares: static void main(String[] a) void main() -> ran: static main(String[])
|
||||
S0_iS declares: static void main() void main(String[] a) -> ran: instance main(String[])
|
||||
SS_S0 declares: static void main(String[] a) static void main() -> ran: static main(String[])
|
||||
IS_I0 declares: void main(String[] a) void main() -> ran: instance main(String[])
|
||||
-- same four classes, compiled first and launched as a class (java -cp out NAME)
|
||||
SS_i0 -> ran: static main(String[])
|
||||
S0_iS -> ran: instance main(String[])
|
||||
SS_S0 -> ran: static main(String[])
|
||||
IS_I0 -> ran: instance main(String[])
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
$ java broken/NoMain.java (JDK 25)
|
||||
broken/NoMain.java:1: error: compact source file does not have main method in the form of void main() or void main(String[] args)
|
||||
void greet() { IO.println("hi"); }
|
||||
^
|
||||
1 error
|
||||
error: compilation failed
|
||||
|
||||
$ java broken/NoIoPrefix.java (JDK 25)
|
||||
broken/NoIoPrefix.java:2: error: cannot find symbol
|
||||
println("hello");
|
||||
^
|
||||
symbol: method println(String)
|
||||
location: class NoIoPrefix
|
||||
1 error
|
||||
error: compilation failed
|
||||
|
||||
$ java broken/NotInJavaBase.java (JDK 25)
|
||||
broken/NotInJavaBase.java:2: error: cannot find symbol
|
||||
HttpClient client = HttpClient.newHttpClient();
|
||||
^
|
||||
symbol: class HttpClient
|
||||
location: class NotInJavaBase
|
||||
broken/NotInJavaBase.java:2: error: cannot find symbol
|
||||
HttpClient client = HttpClient.newHttpClient();
|
||||
^
|
||||
symbol: variable HttpClient
|
||||
location: class NotInJavaBase
|
||||
2 errors
|
||||
error: compilation failed
|
||||
|
||||
$ java broken/WithPackage.java (JDK 25)
|
||||
broken/WithPackage.java:1: error: compact source file should not have package declaration
|
||||
package demo;
|
||||
^
|
||||
1 error
|
||||
error: compilation failed
|
||||
|
||||
$ javac -d out broken/Other.java broken/Target.java (JDK 25; Target.java is a compact file)
|
||||
broken/Other.java:2: error: Target is abstract; cannot be instantiated
|
||||
Target t = new Target();
|
||||
^
|
||||
broken/Other.java:3: error: cannot find symbol
|
||||
t.main();
|
||||
^
|
||||
symbol: method main()
|
||||
location: variable t of type Target
|
||||
2 errors
|
||||
|
||||
$ java broken/Other.java (JDK 25; source launcher, Target.java sits next to it)
|
||||
broken/Other.java:2: error: Target is abstract; cannot be instantiated
|
||||
Target t = new Target();
|
||||
^
|
||||
1 error
|
||||
error: compilation failed
|
||||
|
||||
$ java broken/WrongParam.java (JDK 25)
|
||||
broken/WrongParam.java:1: error: compact source file does not have main method in the form of void main() or void main(String[] args)
|
||||
void main(int count) { IO.println("count = " + count); }
|
||||
^
|
||||
1 error
|
||||
error: compilation failed
|
||||
|
||||
$ java broken/PrivateMain.java (JDK 25)
|
||||
error: can't find main(String[]) or main() method in class: PrivateMain
|
||||
|
||||
$ java broken/CtorWithArgs.java (JDK 25)
|
||||
error: can't find no argument constructor in class: CtorWithArgs
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
$ java broken/PrivateCtor.java (OpenJDK Runtime Environment Temurin-25.0.4.1+1 (build 25.0.4.1+1-LTS))
|
||||
instance main() reached through a PRIVATE zero-argument constructor
|
||||
|
||||
$ java broken/PrivateCtor.java (OpenJDK Runtime Environment Temurin-27+35 (build 27+35))
|
||||
error: no non-private zero argument constructor found in class PrivateCtor
|
||||
remove private from existing constructor or define as:
|
||||
public PrivateCtor()
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
$ javap -p java.lang.IO
|
||||
Compiled from "IO.java"
|
||||
public final class java.lang.IO {
|
||||
private static java.io.BufferedReader br;
|
||||
private java.lang.IO();
|
||||
public static void println(java.lang.Object);
|
||||
public static void println();
|
||||
public static void print(java.lang.Object);
|
||||
public static java.lang.String readln();
|
||||
public static java.lang.String readln(java.lang.String);
|
||||
static synchronized java.io.BufferedReader reader();
|
||||
}
|
||||
|
||||
$ javap -p -c java.lang.IO | grep -E 'public static|System.out|readLine|IOError'
|
||||
public static void println(java.lang.Object);
|
||||
0: getstatic #14 // Field java/lang/System.out:Ljava/io/PrintStream;
|
||||
public static void println();
|
||||
0: getstatic #14 // Field java/lang/System.out:Ljava/io/PrintStream;
|
||||
public static void print(java.lang.Object);
|
||||
0: getstatic #14 // Field java/lang/System.out:Ljava/io/PrintStream;
|
||||
10: invokevirtual #31 // Method java/io/PrintStream.flush:()V
|
||||
public static java.lang.String readln();
|
||||
3: invokevirtual #40 // Method java/io/BufferedReader.readLine:()Ljava/lang/String;
|
||||
8: new #48 // class java/io/IOError
|
||||
13: invokespecial #50 // Method java/io/IOError."<init>":(Ljava/lang/Throwable;)V
|
||||
public static java.lang.String readln(java.lang.String);
|
||||
Reference in New Issue
Block a user