[HN Gopher] JEP 457: Class-File API for Parsing, generating, tra...
       ___________________________________________________________________
        
       JEP 457: Class-File API for Parsing, generating, transforming Java
       classfiles
        
       Author : carimura
       Score  : 89 points
       Date   : 2023-09-26 13:40 UTC (9 hours ago)
        
 (HTM) web link (openjdk.org)
 (TXT) w3m dump (openjdk.org)
        
       | cogman10 wrote:
       | This is the sort of thing that will have a LARGE impact on the
       | ecosystem for updating from one JDK to the next.
       | 
       | One of the big headaches we see with moving up JDK version is
       | bytecode generation/manipulation libraries choking on newer
       | versions of the JDK. It's generally a simple update, but
       | sometimes it's not (for example, when someone is shading asm).
       | 
       | Having bytecode generation as part of the JDK will mean all
       | libraries, including asm, can migrate to that and benefit from a
       | perpetually supported API that updates as the JDK does.
       | 
       | This is probably 80% of the headaches I've experienced going from
       | the likes of Java 11 to 17 and 17 to 21.
        
         | [deleted]
        
       | exabrial wrote:
       | This is pretty exciting... I've used them all libraries at this
       | point in my career: CGLib, ASM, BCEL, ByteBuddy, Javassist,
       | etc... each has its pluses and minuses. I've designed everything
       | from profiling agents, to systems that pack decimals into EBCDIC
       | and invoke COBOL programs on big IBM iron, to lightweight JIT
       | compilers, all using these libraries.
       | 
       | > In 2002, the visitor approach used by ASM seemed clever
       | 
       | I couldn't agree more. The visitor pattern was very hard to
       | explain/justify back then, and still difficult to explain to
       | newbie programmers just entering the profession.
       | 
       | Looking at the examples, I think this is going to be an official
       | replacement for ASM, meaning it's going to be pretty low level.
       | The use of streams pretty straightforward.
       | 
       | If anyone from the JEP is reading this: I have two pieces of
       | feedback!
       | 
       | First, take some inspiration from the way CDI Portable Extensions
       | work. This is probably the most delightful extension API I've
       | ever used. The @Observe callbacks are super simple to explain to
       | people and it's really easy to write extensions for the
       | framework.
       | 
       | Next, I wouldn't ignore the need for a higher-level API akin to
       | ByteBuddy or Javassist. Sometimes I just want to write an
       | interpreter or intercept a method call and thats it.
       | 
       | For example in my Junit/Mockito extension
       | https://github.com/exabrial/mockito-object-injection I need to
       | intercept a call to the class under test in order to lazily
       | inject dependencies at the last possible moment. While I
       | certainly could do this with ASM, Javassist makes this fairly
       | simple with it's MethodHandler api.
       | 
       | Side note, it's a damn shame we don't have a mobile operating
       | system that is JVM native :/ All this cool APIs simply never
       | reach a huge number of devices.
        
         | nvm0n2 wrote:
         | Surely the problem you're objecting to is that Android _is_ JVM
         | native, so the Java APIs are a part of the OS itself.
        
         | vips7L wrote:
         | I just want to share my support of CDI extensions. They just
         | make sense!
        
         | xxs wrote:
         | >First, take some inspiration from the way CDI Portable
         | Extensions work
         | 
         | It's way too late, the API is effectively locked in preview
         | mode.
         | 
         | While I am not a fan of ASM's visitor pattern, explaining it to
         | anyone would be the least of my concerns, ASM requires pretty
         | extensive knowledge on class structure, method signatures, and
         | most of the byte code instructions. Whoever ventures in byte
         | code editing mode should be able to read the byte code
         | directly.
        
         | twic wrote:
         | How would something like CDI portable extensions fit in here?
         | Are you thinking it would another way to replace ASM's
         | visitors? Doesn't it lack all the useful structure that the
         | design in the JEP as, around streaming and building and
         | transformation and so on?
        
           | exabrial wrote:
           | I meant the "style of" CDI portable extensions :)
           | 
           | When you write a CDI portable extension, you register a bunch
           | of observation handlers. So as the CDI environment is
           | discovering stuff, it calls your observers and you have the
           | chance to make chances to the runtime. I was thinking
           | something akin to that here... when reading a class, your
           | observers get called and you have a chance to manipulate the
           | class data.
           | 
           | I find this style intuitive.
        
       | lemming wrote:
       | I wonder if this will be available as a standalone library for
       | older JDKs, it looks very nice.
        
       | spreiti wrote:
       | I highly recommend you to watch this video by Brian Goetz if you
       | want to learn more about this JEP.
       | 
       | https://youtu.be/pcg-E_qyMOI
        
         | shellac wrote:
         | And as a companion piece I really enjoyed Paul Sandoz's 'Code
         | Reflection' talk https://www.youtube.com/watch?v=xbk9_6XA_IY,
         | which considers how java code might understand java code. The
         | sort of thing that enable pushing functions to SQL or GPUs for
         | example.
         | 
         | Edit to add: slides here
         | https://cr.openjdk.org/~psandoz/conferences/2023-JVMLS/Code-...
        
           | bafe wrote:
           | Interesting, but I don't see how operating on the code model
           | is going to be any easier than working on the AST. It seems
           | much more hard to reason about many transformations as
           | compared to manipulating the AST. I do hope they take
           | inspiration from scala and rust macros
        
         | waynesonfire wrote:
         | At round 8:50, Goetz talks about the design, in essence the
         | quote is,
         | 
         | "We designed it as a functional library because functionally
         | inspired libraries are successful at meeting these goals."
         | 
         | Ironic.
        
       | wpollock wrote:
       | Will this enable lombok officially?
        
         | exabrial wrote:
         | Lombok is a compiler extension, where this is an API for the
         | JVM. So two very different things. Think of Lombok/compiler
         | extensions as #include directives in C... things that happen at
         | compile time. This API is for writing programs at runtime, past
         | the compile phase.
        
           | pron wrote:
           | Lombok is not a compiler extension. Compiler extensions, aka
           | annotation processors, are offered only specific capabilities
           | that ensure that they preserve the Java language
           | specification. Particularly, code that compiles successfully
           | with an extension also compiles without it (perhaps requiring
           | other classes to be available) and it compiles down to the
           | same bytecode. Annotation processors are used to implement
           | pluggable type systems (e.g. https://checkerframework.org) or
           | to generate other classes (e.g.
           | https://immutables.github.io/).
           | 
           | Unlike compiler extensions, Lombok compiles source files that
           | do not conform to the Java language specification. Lombok is
           | an alternative Java Platform language, like Clojure or Kotlin
           | or Scala, except that it's a superset of the Java language.
           | However, rather than forking `javac` source code and
           | modifying it to compile Lombok source files, the Lombok
           | compiler modifies `javac`'s operation by hacking into its
           | internals and modifying them as it runs to compile Lombok
           | sources rather than Java sources.
           | 
           | Having alternative Java Platform languages is perfectly fine.
           | The problem with Lombok is that it doesn't present itself as
           | such but as a library or a compiler extension even though it
           | violates the Java language specification in ways that
           | compiler extensions are forbidden from doing.
        
         | cogman10 wrote:
         | Lombok's headaches are because they are touching Java compiler
         | internals to accomplish their magic. This won't fix that.
         | 
         | Lombok wouldn't be nearly as troubled if it was just doing
         | simple bytecode manipulation.
         | 
         | If lombok wants to stop the pain, then they'll need to stop
         | reaching into internal APIs. They'll possibly need to remove a
         | few features (like some of the `private final` work they are
         | doing).
         | 
         | In other words, you can expect lombok to be a headache for
         | years to come. (Maybe consider not using it? That'd be swell.
         | Speaking as someone that curses lombok everytime jdk updates
         | roll around.)
        
           | the-smug-one wrote:
           | Why isn't Lombok just written as a pre-javac pass?
           | javac(lombok(srccode)). Just gotta keep that parser alive and
           | up to date, which open source IDEs also must so they're
           | probably available.
        
             | tmccrary55 wrote:
             | It's easier (read more reliable) to manipulate bytecode or
             | other internal representation than the source.
        
               | aardvark179 wrote:
               | Manipulating the AST would be fine, but Lombok pretends
               | to be an annotation processor (which can generate new
               | classes, but not alter the semantics of the class being
               | processed). They could create lombokc and crack open the
               | internals of the Java compiler as much as they like, but
               | this would mean admitting they are really Java, and they
               | don't seem to want to accept that.
        
         | xxs wrote:
         | Lombok should not be touched, esp. since records have been
         | available. Morealso, lombok is just a sugar coating during
         | compilation time.
         | 
         | Even before records, just use public final fields, and be done
         | with the getter/setter nonsense. (IDEs do a good job of
         | offering options for toString(), and c-tors)
         | 
         | Personally, I consider lombok one of the better anti-patterns
         | widely used.
        
           | javanonymous wrote:
           | Lombok can be used for more than just getters/setters.
           | 
           | I personally use the _@Builder_ annotation on records with
           | more than 3-4 fields. I find it much more readable than a
           | long list of arguments to the constructor.
           | 
           | It also makes it easy to return a copy of the record where
           | only a few fields have changed:                  var r =
           | book.toBuilder()                         .lastUpdated(now)
           | .title("...")                .build()
           | 
           | I also use other annotations, but I could work without them
           | if a future version of Java provides a builder-like pattern
           | (or named arguments)
        
             | bafe wrote:
             | This design note could be of interest:
             | https://github.com/openjdk/amber-docs/blob/master/eg-
             | drafts/...
        
           | ImprobableTruth wrote:
           | Records are the way to go, but there are many situations
           | where the ecosystem doesn't work with them e.g. if you're
           | stuck using something like Hibernate.
        
       ___________________________________________________________________
       (page generated 2023-09-26 23:01 UTC)