/r/java

Photograph via snooOG

News, Technical discussions, research papers and assorted things of interest related to the Java programming language

NO programming help, NO learning Java related questions, NO installing or downloading Java questions, NO JVM languages - Exclusively Java

Submit Text

Seek Programming Help

News, Technical discussions, research papers and assorted things of interest related to the Java programming language

NO programming help, NO learning Java related questions, NO installing or downloading Java questions, NO JVM languages - Exclusively Java

These have separate subreddits - see below.

Please seek help with Java programming in /r/Javahelp!

Subreddit rules!

Upvote good content, downvote spam, don't pollute the discussion with things that should be settled in the vote count.

  • Do not post tutorials here! These should go in /r/learnjava.
  • No programming help questions here! These should be posted in /r/javahelp
  • No surveys, no job offers! Such content will be removed without warning.

Where should I download Java?

With the introduction of the new release cadence, many have asked where they should download Java, and if it is still free. To be clear, YES — Java is still free.

If you would like to download Java for free, you can get OpenJDK builds from the following vendors, among others:

Adoptium (formerly AdoptOpenJDK)
RedHat
Azul
Amazon
SAP
Liberica JDK
Dragonwell JDK
GraalVM (High performance JIT)
Oracle
Microsoft

Some vendors will be supporting releases for longer than six months. If you have any questions, please do not hesitate to ask them!

Related Sub-reddits:

Programming
Computer Science

CS Career Questions

Learn Programming
Java HelpSeek help here
Learn Java
Java Conference Videos
Java TIL
Java Examples
JavaFX
Oracle

JVM Languages

Clojure
Scala
Groovy
ColdFusion
Kotlin

Want to practice your coding?

DailyProgrammer
ProgrammingPrompts
ProgramBattles

List of useful Frameworks / Libraries / Software

Awesome Java (GIT)
Java Design Patterns

/r/java

346,323 Subscribers

13

Is GraalVM the Go-To Choice?

Do you guys use GraalVM in production?

I like that GraalVM offers a closed runtime, allowing programs to use less memory and start faster. However, I’ve encountered some serious issues:

  1. Compilation Time: Compiling a simple Spring Boot “Hello World” project to a native image takes minutes, which is hard to accept. Using Go for a similar project only takes one second.

  2. Java Agent Compatibility: In the JVM runtime, we rely on Java agents, but it seems difficult to migrate this dependency to a native image.

  3. GC Limitations: GraalVM’s community version GC doesn’t support G1, which could impact performance in certain memory-demanding scenarios.

For these reasons, we felt that migrating to GraalVM was too costly. We chose Go, and the results have been remarkable. Memory usage dropped from 4GB to under 200MB.

I’d like to know what others think of GraalVM. IMO, it might not be the “go-to” choice just yet.

34 Comments
2024/11/03
11:48 UTC

4

Java bytecode obscurification suggestions?

I want to release a demo of a game I've been working on as a jar. I'd feel more comfortable if the jar was obsurified (I think that's a word). I have used proguard in the past but I simply haven't a clue how the current version works - it seems to be for Android and something called Gradle. I just want a simple obscurifier that's easy to use, takes a jar with a few options and outputs the obscurified jar.

Any suggestions?

17 Comments
2024/11/03
10:38 UTC

11

Coming to Springboot from Jax-rs

This is probably a question asked many times before but my question is not specifically about using one or the other. I come from a Jax-rs background and most things are done manually. I recently read the Spring In Action book and tried out Springboot and it seems super easy to use and I quite like it.

However, after reading about Springboot I found out that it silently enables OSIV (Open Session in View) which imo is something that should be disabled by default and you should enable it only if you want.

What other things are silently enabled (or handled magically) in Springboot that is worth knowing? Is there a place in their documentation to see what's enabled by default?

6 Comments
2024/11/03
05:03 UTC

1

A new way to explore the open source Java ecosystem

Hi! I'm making a resource to help explore different software ecosystems called Echo, and I made a directory for Java: https://ecosystems.gitwallet.co/ecosystems/java/

You can think of this as a different take on Github Explore (although we're getting repos from Gitlab as well), but also featuring some of the people in the community too. I think we need better tools for exploring open source in this way, and we're experimenting with it.

We also made a different take on the Github repo page to make it a bit more readable, see related repos, and a few more things. Here's an example for GraalVM, which compiles Java into native executables:

https://ecosystems.gitwallet.co/ecosystems/java/projects/graal

Anyways would love some feedback from other folks from the Java ecosystem! I learned Java early in my career (J2SE/J2ME days!!) but haven't quite kept up with the ecosystem to be frank, so hoping that folks here might be able to smoketest this - let me know if / how it's useful to you!

Thanks so much!!

3 Comments
2024/11/03
00:29 UTC

21

Automatic Relationship Finder(ARF)

Relationship Finder (ARF), a Java library designed to automatically detect implicit relationships between database tables. Perfect for OLTP databases where foreign key constraints may be missing, ARF is here to make data cataloging, ETL workflows, and data migration simpler and more effective.

Check out the full release notes and download ARF v1.0-beta.1.0 on GitHub:https://github.com/NoelToy/automatic-relationship-finder Looking forward for feedback or feature requests for future releases!

20 Comments
2024/11/02
12:43 UTC

8

Httpcomponent client 5.4 experience s?

Hi,

I finally got around to upgrade our legacy app to Spring boot 3. So, time to hit the new java 21 goodness. I noticed that Spring boot supports it,(through tomcat).

But for our outbound connections we use httpcomponent client. I see that 5.4 claims to be able to use virtual threads. Does anybody have experience with that? And any indication of performance increase?

I've looked around and couldn't really find anything (but maybe it's because people nowadays use different clients).

9 Comments
2024/11/01
16:45 UTC

12

Tip & Tail - Release Your (Java) Projects Like OpenJDK

0 Comments
2024/10/31
14:52 UTC

23

JDK 23's Javadoc sidebar is annoying

As much as I appreciate the effort to keep on improving the look and feel of Javadoc, the recent change to the sidebar in JDK 23 feels like it needs some adjustment.

First, the width is insanely large. This has been acknowledged and has been decreased in JDK 24, but I don't feel that it's enough. Even if I use with Chrome DevTools to apply the changes from JDK 24, I still find the resulting sidebar way too wide. A value of flex: 5 1 0 feels more realistic, at least on a desktop monitor...

And then there is the question of having a fixed width to begin with. Why is the side-bar no longer resizeable?

Am I the only one who feels this way?

(I am viewing the Javadoc on a 4k monitor, with a resolution of 3840 x 2160)

23 Comments
2024/10/31
12:36 UTC

7

ASMifier Gradle plugin

For those who'd like to do some bytecode manipulation using ASM and aren't too sure of how to write some instructions with it, ASM utils provides a tool called ASMifier that converts a compiled ".class" file into ASM instructions.

While helpful, using that tool requires a couple of manual steps and it can only transform one ".class" file at a time. So I created this gradle plugin to hopefully make that process more straightforward. You're welcome to take a look!

0 Comments
2024/10/31
10:54 UTC

9

SafeSql - Injection-safe Jdbc Template

From a recent discussion thread in this sub, I couldn't help giving it a try and wrote the SafeSql class, a JDBC SQL template, as inspired by JEP 459 (String Template).

If you use a ORM framework, it doesn't help you. But for some of us who write raw SQL, it could be interesting I think.

Goals:

  1. Harden protection against SQL injection. By designing the DAO layer to reject String and only accept SafeSql, it should be verifiably safe even if the sql is passed in from another team (unless they intentionally write malicious SQL of course).
  2. A mini DSL that makes it easy to compose subqueries and create dynamic queries.

That probably sounds similar to JEP 459 too (point #2 still remains to be seen). While the JEP is still under development, I can imagine the syntax not far from this when it arrives:

UserCriteria criteria = ...;
Result result = dao.query(
    """
    SELECT firstName, lastName from Users
    WHERE firstName like '%${criteria.firstName()}%'
    OR lastName like '%${criteria.lastName()}%'
    """ );

The Dao class will translate the SQL to:

   SELECT firstName, lastName from Users
    WHERE firstName like ?
    OR lastName like ?

And if it uses java.sql.PreparedStatement under the hood, the code likely does this to populate the statement:

 statement.setObject(1, "%" + criteria.firstName() + "%"); 
 statement.setObject(2, "%" + criteria.lastName() + "%");

Syntax and runtime semantics

SafeSql syntax is very close to the presumed JEP interpolation:

SafeSql sql = SafeSql.of(
    """
    SELECT firstName, lastName from Users
    WHERE firstName LIKE '%{first_name}%'
    OR lastName LIKE '%{last_name}%'
    """,
    criteria.firstName(), criteria.lastName());
PreparedStatement statement = sql.prepareStatement(connection);

But of course without the language support, the library has to manually pass the parameters, which adds verbosity.

The upside? There's a compile-time plugin that protects you from passing in the wrong number of parameters, or passing them in the wrong order (you get a compile-time error if you do).

Runtime-behavior is the same.

A more interesting example

I recently learned of the Spring JdbcOperations.queryForMap(). A fair question then is: how is this different from:

 queryForMap("SELECT ... '%?%' ... '%?%'", criteria.firstName(), criteria.lastName()) ? 

Admittedly queryForMap() gives the same level of convenience. There is the compile-time plugin which makes some difference fwiw, but let's first look at a more realistic example where queryForMap() doesn't help, period.

Imagine the UserCriteria class has some optional criteria: if the client has provided firstName, then query by firstName; if provided lastName then query by lastName; if provided user id, query by id; otherwise return all. The UserCriteria class may look like:

class UserCriteria {
  Optional<String> firstName();
  Optional<String> lastName();
  Optional<String> userId();
}

queryForMap() can't handle it now. If I am to implement this from ground up using dynamic sql, it may look like this:

StringBuilder sqlBuilder = new StringBuilder(
    "SELECT firstName, lastName from Users WHERE 1 = 1");
List<Object> args = new ArrayList<>();
criteria.firstName().ifPresent(n -> {
    sqlBuilder.append(" AND firstName LIKE ?");
    args.add("%" + n + "%");
});
criteria.lastName().ifPresent(n -> {
    sqlBuilder.append(" AND lastName LIKE ?");
    args.add("%" + n + "%");
});
criteria.userId().ifPresent(id -> {
    sqlBuilder.append(" AND id = ?");
    args.add(id);
});
PreparedStatement stmt = connection.prepareStatement(sqlBuilder.toString());
for (int i = 0; i < args.size(); i++) {
  stmt.setObject(i + 1, args.get(i));
}

It's probably not that bad, right? But why not wish for better? And if you allow random dynamic string building, it won't be easy to harden the injection protection across the board: how do you know the sql passed in by another programmer from another team didn't accidentally use a user-provided string?

In comparison, this is what the "mini DSL" looks like with SafeSql:

import static ... SafeSql.optionally;

SafeSql sql = SafeSql.of(
    "SELECT firstName, lastName from Users WHERE {criteria}",
    Stream.of(
          optionally("firstName LIKE '%{first_name}%'", criteria.firstName()),
          optionally("lastName LIKE '%{last_name}%'", criteria.lastName()),
          optionally("id = {id}", criteria.userId()))
      .collect(SafeSql.and()));

The code is relatively self-evident: a query whose WHERE clause being 3 optional sub-clauses ANDed together. If for example criteria.firstName() returns empty, the firstName LIKE ? subclause is skipped.

It also gracefully handles the case if all of the optional subclauses are empty.

This mainly demonstrates the benefit of the goal #2: being able to compose simpler queries to create more complex queries allows code reuse and makes the mini DSL readable.

And due to this composability, more generic helper methods like optionally() could be built to compose SQL safely for other common dynamic SQL use cases if needed.

What's not obvious though, is the compile-time guardrail: with the choice of placeholder name {first_name}, if I accidentally used criteria.lastName() in the place of first_name, I get a compilation error.

Hardening

So how does this class harden the injection protection? It uses ErrorProne's @CompileTimeConstant annotation in places it expects a string template and you are not allowed to pass a dynamic string.

You can of course pass any string as the placeholder args, but they will be sent as JDBC parameters safely, except SafeSql args: they are treated as subqueries.

For provably safe dynamic SQL compositions, the class provides common helpers such as and(), or(), joining(), when() etc.

In a nutshell, SafeSql is a "walled garden" where only provably safe strings are allowed to build dynamic sql.

Usability

I don't do JDBC in my day-to-day work. So I'm curious if there are real-life scenarios that're not covered. For one, the @CompileTimeConstantcheck is quite strict.

So the question is: is this walled garden sufficiently usable?

Let me know if this can be useful to you or what you see missing?

27 Comments
2024/10/30
17:18 UTC

41

Total memory needed for nullable primitives with Valhalla

Currently the overhead of using a nullable primitive like Integer is

compressed pointer size + additional object in case it's not from a built in pool like small int pool.

How does that change with Valhalla? In theory only one additional bit is sufficient to add nullability to any primitive type. But does Valhalla take it that far?

28 Comments
2024/10/30
12:04 UTC

25

FreshMarker 1.6.5 released

i have released a new version of my Java 21 template engine FreshMarker.

https://gitlab.com/schegge/freshmarker

15 Comments
2024/10/30
07:36 UTC

25

33 Comments
2024/10/28
15:20 UTC

5

Java Command in-line tool for saving directories and filepaths and resolving them easiely

1 Comment
2024/10/27
17:01 UTC

51

Better Java Builds with the Mill Build Tool, Japan Java User Group Fall Conference 2024

26 Comments
2024/10/27
12:00 UTC

120

Why does the List interface have forEach, but not map?

Pretty much the title: It's kind of annoying and "bloaty" to create a Stream from the List, just to do a map (or filter) and then convert it back to List. Isn't it also inefficient?

Is there a solid, philosophical justification behind this choice, or it is like that mostly for backward compatibility?

And on a broader, more non-orthodox note, why isn't every List a Stream? I fully understand the other way round, i.e. obviously not every Stream is a List, but this way..

Thanks a lot

91 Comments
2024/10/26
14:05 UTC

34

Accelerating performance of Java applications on Arm64 by Dave Neary (Devoxx 2024)

2 Comments
2024/10/25
17:25 UTC

Back To Top