Welcome to the new Inside Java Podcast. In this meta episode, Nicolai Parlog introduces you to the podcast’s new structure with two shows under one umbrella: The long-form conversations you know become Ask the Architects episodes and they’ll be accompanied by the Inside Java Newscast as a podcast.
Make sure to also check the Duke’s Corner podcast on dev.java.
For more episodes, check out Inside Java, our YouTube playlist, and follow @Java on Twitter.
Contact us here.
]]>]]>
The OpenJDK Quality Group is promoting the testing of FOSS projects with OpenJDK builds as a way to improve the overall quality of the release. This heads-up is part of a regular communication sent to the projects involved. To learn more about the program, and how-to join, please check here.
Before the introduction of try-with-resources and the Cleaner API, classes that needed to release resources before their end of life would implement Object.finalize().
The garbage collector invokes this method after an object becomes unreachable and before reclaiming its memory.
This process, known as finalization, has a difficult programming model that is prone to unreliable implementation, can cause security vulnerabilities, and negatively impacts performance.
It has thus been deprecated for removal in favor of the aforementioned alternatives in JDK 18, as described in JDK Enhancement Proposal 421.
Since then, the number of finalize implementations in the JDK has been steadily reduced.
Likewise, the Java ecosystem is required to search for and remove finalize implementations to prepare for the eventual removal of this mechanism.
See JEP 421 for details how to approach this.
ThreadPoolExecutor is a non-final implementation of ExecutorService that may be a superclass to executor services in frameworks, libraries, and applications.
Its finalize-method has been…
JDK 27 will remove the empty method, which can lead to compile errors in existing code.
While Object.finalize() declares that it throws Throwable, ThreadPoolExecutor.finalize() does not.
That means calls to ThreadPoolExecutor.finalize(), either directly or by an extending class through super.finalize(), will now implicitly call Object.finalize() and thus encounter a Throwable when they didn’t before, which is likely to result in a compile error.
Projects encountering this situation are strongly encouraged to remove this (and other) uses of finalize().
If absolutely necessary, a workaround would be to encase the invocation of finalize() in a try block.
Since this ends up calling Object.finalize(), which is empty, the catch block can likewise be empty.
The OpenJDK Quality Group is promoting the testing of FOSS projects with OpenJDK builds as a way to improve the overall quality of the release. This heads-up is part of the quality outreach sent to the projects involved. To learn more about the program, and how-to join, please check here.
Since JDK 21, java.text.DecimalFormat::format and java.util.Formatter::toString produce slightly different outcomes on some double values, like the one from the snippet bellow.
double value = 7.3879E20;
int minFractionDigits = 0;
DecimalFormat df = (DecimalFormat) NumberFormat.getNumberInstance(Locale.ROOT);
df.setGroupingUsed(false);
df.setMinimumFractionDigits(minFractionDigits);
IO.println(df.format(value); // prints 738790000000000100000
Formatter fmt = new Formatter(Locale.ROOT);
fmt.format("%." + minFractionDigits + "f", value);
IO.println(fmt.toString()); // prints 738790000000000000000
This rare situation occurs because java.util.Formatter and Double.toString() use an algorithm enhanced in JDK 21.
A fix was introduced in JDK 26 for the java.text.DecimalFormat implementation to use the same algorithm as java.util.Formatter and Double.toString(), thus producing the same outcome.
For a few releases, java.text.DecimalFormat will still offer the old algorithm to help migrate applications affected by this change. You can enable the old algorithm by appending -Djdk.compat.DecimalFormat=true to your java command; otherwise, the new algorithm runs.
We encourage you to download the JDK 26 Early Access builds, evaluate the behavior of your application and prepare to migrate if you see any impact. Feedback is also welcomed through the jdk-dev mailing list (registration required). For more details on this change, check the JBS issue JDK-8362448 and the release notes.
Lazily initializing fields in Java is error-prone and undermines constant-folding. JDK 26 comes with JEP 526, which previews LazyConstant, a type that lazily initializes a value through a given Supplier. It executes that supplier at most once successfully and then assigns the value to a field annotated with @Stable, which allows constant folding. This API is also a poster child for how OpenJDK develops and evolves features.
Make sure to check the show-notes.
]]>This session demonstrates how LangChain4j can help, showcasing a set of often overlooked techniques that keep AI systems on track and unlock more advanced use cases. We explore LangChain4j’s advanced RAG methods for finding all relevant information across documents, databases, APIs, and more, and share practical tips for effective tool calls and responsible MCP usage. You will also see how LangChain4j’s agentic approach lets you decompose complex workflows for greater clarity and control. The presentation wraps up with a guided build of a production-ready agentic system, including the operational and legal considerations that matter once you move beyond PoC.
Recorded at Devoxx Belgium 2025.
]]>In this special episode of the Inside Java Podcast, Nicolai Parlog talks to Adam Bien about scripting with Java, to Maurice Naftalin about the history and tradeoffs of the collections framework and erasure, and to Tom Cools about the innovative way the Belgian Java User Group organizes itself.
Make sure to also check the Duke’s Corner podcast on dev.java.
For more episodes, check out Inside Java, our YouTube playlist, and follow @Java on Twitter.
Contact us here.
]]>