From scolebourne at joda.org Thu Oct 6 11:27:06 2022 From: scolebourne at joda.org (Stephen Colebourne) Date: Thu, 6 Oct 2022 12:27:06 +0100 Subject: Java on-ramp - Class declaration for Entrypoints Message-ID: Hi all, I wrote up my response to the on-ramp discussion as a blog post having given it a few days thought: https://blog.joda.org/2022/10/fully-defined-entrypoints.html I think what I've come up with is a lot more powerful, more useful to experienced developers, and more consistent during the learning process. It is, of course, a bigger change. This email to amber-spec-comments reads the idea into the legal-world of OpenJDK.. thanks Stephen

Entrypoints

When a Java program starts some kind of class file needs to be run. It could be a normal class, but that isn't ideal as we don't really want static/instance variables, subclasses, parent interfaces, access control etc. One suggestion was for it to be a normal interface, but that isn't ideal as we don't want to mark the methods as default or allow abstract methods.

I'd like to propose that what Java needs is a new kind of class declaration for entrypoints.

I don't think this is overly radical. We already have two alternate class declarations - record and enum. They have alternate syntax that compiles to a class file without being explictly a class in source code. What we need here is a new kind - entrypoint - that compiles to a class file but has different syntax rules, just like record and enum do.

I believe this is a fundamentally better approach than the minor tweaks in the official proposal, because it will be useful to developers of all skill levels, including framework authors. ie. it has a much better "bang for buck".

The simplest entrypoint would be:

  // MyMain.java
  entrypoint {
    SystemOut.println("Hello World");
  }

In the source code we have various things:

The classes like SystemOut may seem like a small change, but it would have been much simpler for me from 25 years ago to understand. I don't favour more static imports for them (either here or more generally), as I think SystemOut.println("Hello World") is simple enough. More static imports would be too magical in my opinion.

The next steps when learning Java are for the instructor to expand the entrypoint.

Here are some valid examples. Note that instructors can choose the order to explain each feature:

  entrypoint {
    SystemOut.println("Hello World");
  }
  entrypoint main() {
    SystemOut.println("Hello World");
  }
  entrypoint main(String[] args) {
    SystemOut.println("Hello World");
  }
  entrypoint {
    main() {
      SystemOut.println("Hello World");
    }
  }
  entrypoint {
    void main(String[] args) {
      SystemOut.println("Hello World");
    }
  }
  entrypoint {
    main(String[] args) {
      output("Hello World");
    }
    output(String text) {
      SystemOut.println(text);
    }
  }

Note that there are never any static methods, static variables, instance variables or access control. If you need any of that you need a class. Thus we have proper separation of concerns for the entrypoint of systems, which would be Best Practice even for experienced developers.

Progressing to classes

During initial learning, the entrypoint class declaration and normal class declaration would be kept in separate files:

  // MyMain.java
  entrypoint {
    SystemOut.println(new Person().name());
  }
  // Person.java
  public class Person {
    String name() {
      return "Bob";
    }
  }

However, at some point the instructor would embed an entrypoint (of any valid syntax) in a normal class.

  public class Person {
    entrypoint {
      SystemOut.println(new Person().name());
    }
    String name() {
      return "Bob";
    }
  }

We discover that an entrypoint is normally wrapped in a class which then offers the ability to add static/instance variables and access control.

Note that since all methods on the entrypoint are private and the entrypoint is anonymous, there is no way for the rest of the code to invoke it without hackery. Note also that the entrypoint does not get any special favours like an instance of the outer class, thus there is no issue with no-arg constructors - if you want an instance you have to use new (the alternative is unhelpful magic that harms learnability IMO).

Finally, we see that our old-style static main method is revealed to be just a normal entrypoint:

  public class Person {
    entrypoint public static void main(String[] args) {
      SystemOut.println(new Person().name());
    }
    String name() {
      return "Bob";
    }
  }

ie. when a method is declared as public static void main(String[]) the keyword entrypoint is implicitly added.

What experienced developers gain from this is a clearer way to express what the entrypoint actually is, and more power in expressing whether they want the command line arguments or not.

Full-featured entrypoints

Everything above is what most Java developers would need to know. But an entrypoint would actually be a whole lot more powerful.

The basic entrypoint would compile to a class something like this:

  // MyMain.java
  entrypoint startHere(String[] args) {
    SystemOut.println("Hello World");
  }
  // MyMain$entrypoint.class
  public final MyMain$entrypoint implements java.lang.Entrypoint {
    @Override
    public void main(Runtime runtime) {
      runtime.execute(() -> startHere(runtime.args()));
    }
    private void startHere(String[] args) {
      SystemOut.println("Hello World");
    }
  }

Note that it is final and methods are private.

The Entrypoint interface would be:

  public interface java.lang.Entrypoint {
    /**
     * Invoked by the JVM to launch the program.
     * When the method completes, the JDK terminates.
     */
    public abstract void main(Runtime runtime);
  }

The Runtime.execute method would be something like:

  public void execute(ThrowableRunnable runnable) {
    try {
      runnable.run();
      System.exit(0);
    } catch (Throwable ex) {
      ex.printStackTrace();
      System.exit(1);
    }
  }

The JVM would do the following:

Note that java.lang.Entrypoint is a normal interface that can be implemented by anyone and do anything!

This last point is critical to enhancing the bang-for-buck. I was intriguied by things like Azul CRaC which wants to own the whole lifecycle of the JVM run. Wouldn't that be more powerful if they could control the whole lifecycle through Entrypoint. Another possibile use is to reset the state when an application has finished, allowing the same JVM to be reused - a bit like Function-as-a-Service providers or build system daemons do. (I suspect it may be possible to enhance the entrypoint concept to control the shutdown hooks and to catch things like System.exit but that is beyond the scope of this blog.) For example, here is a theoretical application framework entrypoint:

  // FrameworkApplication.java - an Open Source library
  public interface FrameworkApplication extends Entrypoint {
    public default main(Runtime runtime) {
      // do framework things
      start();
      // do framework things
    }
    public abstract start();
  }

Applications just implement this interface, and they can run it by specifying their own class name on the command line, yet it is a full-featured framework application!

From till.brychcy at unite.eu Tue Oct 18 06:43:18 2022 From: till.brychcy at unite.eu (Till Brychcy) Date: Tue, 18 Oct 2022 06:43:18 +0000 Subject: Draft JEP: Unnamed local variables and patterns Message-ID: <19CF33F2-EC59-4994-ADBA-92E5C3F3D665@unite.eu> > 7. a resource specification of a try-with-resources statement > > Today we get this warning with a TWR-statement if the local is ignored: > > > > javac -Xlint:all MyScopedLock.java > > MyScopedLock.java:23: warning: [try] auto-closeable resource ignored is never referenced in body of corresponding try statement > try(MyScopedLock ignored = l.lock()) { > ^ > 1 warning > > So here we may have a clash of philosophies for the enhanced-for and how people > use the `AutoCloseable`. We have a similar use case: a logging framework that uses the close() call to measure the runtime of some code block. It looks like this: try (__ __ = ThreadLogger.block(SomeClass.class, "someAction")) { // some code } Note we named the helper class and variable already "__" to make clear that they are not used - before Java 8 we used to called them "_? :-) Big advantages in comparison to e.g. a lambda based solution are that this doesn?t interfere with exceptions and variables outside the try statement can be assigned. There are also more cases reported by other people in https://bugs.eclipse.org/bugs/show_bug.cgi?id=560733 , which why an already implemented warning for such variables by Eclipse was removed again. Wir stellen uns als Marke neu auf und stehen mehr denn je zusammen. Unite ist nun unsere f?hrende Unternehmensmarke. Erfahren Sie mehr Folgen Sie uns auf LinkedIn, Twitter oder YouTube unite.eu Unite Services GmbH & Co. KG, im Auftrag von Unite Unite Network SE Neumarkt 9, 04109 Leipzig, Deutschland | Amtsgericht Leipzig, HRB 39278 ?Vorstand: Dr. Sebastian Wieser (Vorsitzender), Christel Constant, Peter Ledermann, Dr. Bernd Sch?nw?lder ?Aufsichtsrat: Karl Mayer-Rieckh (Vorsitzender) Mercateo Deutschland AG Mercateo Deutschland AG F?rstenfelder Stra?e 5, 80331 M?nchen, Deutschland | Amtsgericht M?nchen, HRB 243681 ?Vorstand: Dr. Sebastian Wieser (Vorsitzender), Christel Constant, Peter Ledermann, Dr. Bernd Sch?nw?lder ?Aufsichtsrat: Karl Mayer-Rieckh (Vorsitzender) mercateo.com/procure -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: image985586.png Type: image/png Size: 4303 bytes Desc: image985586.png URL: