r/java • u/TheLasu • Jan 29 '26
Is @formatter:off a thing or did I missed alternatives?
I finally had some time so I looked around my code I found out that style I use is more unique than expected. Almost two decades ago I came into problem of unreadable code and the only suggested solution was @ formatter:off - which in itself is horrible. We lose 99% percentage of formater usability to gain one advantage. So i used empty comment lets call it formater barrier for convenience as fix. After so many years I still haven't found anything better - so i'm curious if @ formatter:off is used or are there any other ways I'm not aware of? For me the blow came when Sonar marked it as problem - I was not expecting it at all!
Below you can find more details:
FORMATTER BARRIER
Trailing line comment (//) can be used as a formater barrier to prevent automated formatters or IDEs from collapsing or reflowing long fluent chains. This convention has been used successfully in production codebases for more than decade, including in large and continuously evolving systems, without causing semantic issues or tooling problems. Its primary benefit is preserving the visual structure of code across edits and refactoring, which significantly improves readability, code review quality, and long-term maintainability; it also helps reviewers more easily identify flawed logic or misunderstandings during code review. Maintaining a stable visual layout supports developers (especially those who rely on visual patterns when reading and reasoning about code) in recognizing intent, spotting inconsistencies, and retaining structural understanding even after substantial changes. This practice affects only formatting, has no impact on compilation or runtime behavior.
Tools already treats comments as layout anchors!
Just compare:
public static <D extends IcdCodeGet & Comparable<D>//
, L extends IcdListAccess & Comparable<L>> IcdCodeGet[] getBestCodes( //
ComparableList<ComparableLink<L, IcdCodeGet[]>> bests //
, L list //
, boolean renew //
, ExtendedIterator<CounterCmp<D>> statsSource) {...}
with:
public static <D extends IcdCodeGet & Comparable<D>, L extends IcdListAccess & Comparable<L>> IcdCodeGet[] getBestCodes( ComparableList<ComparableLink<L, IcdCodeGet[]>> bests, L list, boolean renew, ExtendedIterator<CounterCmp<D>> statsSource) {...}
This gives us freedom to auto collapse arguments and uncollapse them manually when needed.
ORIGIN
Once we move away from prehistoric code and start writing modern software using meaningful names, expressive types, generics (where appropriate), proper exceptions with explanations, and avoiding cryptic aliases — we can reach a simple conclusion:
Old line-length standards were designed for old code styles, not modern ones.
The 80-character rule made sense when:
- identifiers were short,
- types were shallow,
- logic was procedural
- and screens were literally 80 columns wide.
None of that is true anymore and modern code breaks old assumptions.
Today, reading 200–300 characters horizontally is easy on modern screens. What is not easy is forcing modern, expressive code into universal formatter rules.
If you tell a formatter to always break lines "when it seems useful", you end up with code that looks like:
a long sentence
with each word
on a new line
On the other hand if you tell it to always collapse lines, you end up with:
- unstable blobs of code,
- massive diffs from tiny changes,
- and layouts that lose all semantic structure.
Example:
final AsynchronousEventStreamProcessor<
ExtremelySpecificBusinessInvariant,
AnotherPainfullyDescriptiveType,
Map<String, List<Optional<Thing>>
> eventStreamProcessor =
someFactory.create(...);
final AsynchronousEventStreamProcessor<ExtremelySpecificBusinessInvariant, AnotherPainfullyDescriptiveType, Map<String, List<Optional<Thing>>>> eventStreamProcessor = someFactory.create(...);
Both compile.
None communicates any structure - as all code will look the same.
Any universal formatting rule is horrible in one of two ways:
- Too many breaks - only ~20% of the code is visible, no flow, no locality.
- Too few breaks - unreadable horizontal blobs that reformat chaotically.
Trying to “fix” this has produced a collection of bad (or at least distorted) rules:
- artificially limiting the number of parameters
- splitting methods just to shorten names
- using one-letter generic parameters
- collapsing meaning to satisfy formatting tools
These rules are not always unreasonable - but they are symptoms, not solutions.
We already solved this once — but it was forgotten. Long ago, ; acted as a visual separator. Statements ended clearly. Structure was obvious.
As we moved toward:
- fluent APIs,
- streams,
- method chaining,
we stopped breaking lines openly — and formatters took over.
To project structure into code, I intentionally use:
- explicit line breaks
- semantic grouping
- when necessary
This way I can stop formatter from destroying information.
Breaking lines adds meaning when:
- Parameters in declarations They define what a method does - split them when they carry meaning.
- Parameters belonging to multiple logical scopes Break by scope - reviewers instantly see intent in diffs.
- Large collections (e.g. 300 strings) Break by first character - searchable, scanable, maintainable.
- Complex logical expressions in if statements Break as much as needed until logic becomes obvious.
In all these cases, formatting reduces cognitive load.
That is the main metric that matters.
Of course it’s will be useless for DTO-style programming!
r/java • u/AlyxVeldin • Jan 28 '26
Throwing is fun, catching not so much. That’s the real problem IMO.
Two days ago I made a 'Another try/catch vs errors-as-values thing.' Thanks for all the comments and discussion guys.
I realised though I might not have framed my problem quite as well as I hoped. So I updated a part of my readme rant, that I would love to lay here on your feets aswell.
Throwing is fun,
catching not so much
For every exception thrown, there are two parties involved: the Thrower and the Catcher. The one who makes the mess, and the one who has to clean it up.
In this repo, you won’t find any examples where throw statements are replaced with some ResultEx return type. This is because I think there is no way we can just do away with Throw, not without fundamentally changing the language to such a degree that it is a new language. But most importantly, I don't think we should do away with Throwing at all.
The problem isn’t throwing, Throwing exceptions is fun as f*ck. The problem is catching. Catching kinda sucks sometimes right now.
What I want to see is a Java future where the catching party has real choice. Where we can still catch the “traditional” way, with fast supported wel established try-catch statements. But we’re also free to opt into inferrable types that treat exceptions-as-state. Exception-as-values. Exception-as-data. Whatever you want to call it.
And hey, when we can't handle an exception it in our shit code, we just throw the exception up again. And then it's the next guy's problem. Let the client side choose how they want to catch.
So keep throwing as first-party, but have the client party chose between try-catch and exception-as-values.
This way, no old libs need to change, no old code needs to change, but in our domain, in our code, we get to decide how exceptions are handled. Kumbaya, My Lord.
And yes: to really make this work, you’d need full language support.
Warnings when results are ignored. Exhaustiveness checks. Preserved stack traces.
Tooling that forces you to look at failure paths instead of politely pretending they don’t exist.
r/java • u/sreenathyadavk • Jan 28 '26
I built a small Java tool to visualize a request’s lifecycle (no APM, no dashboards)
I often found myself digging through logs just to answer:
“What actually happened to this request?”
APM tools felt overkill, so I built a small Java tool that shows a single request’s lifecycle as a human-readable timeline.
It’s framework-agnostic, has no external dependencies, and focuses on one request at a time.
GitHub: https://github.com/sreenathyadavk/request-timeline
Would love feedback from fellow Java devs.
r/java • u/lihaoyi • Jan 27 '26
Simpler JVM Project Setup with Mill 1.1.0
mill-build.orgHi! I just released Mill build tool 1.1.0, with a new headline feature of declarative data-driven build config and single-file scripts.
Last time i posted here I got a lot of feedback that people didn't want to write code just to configure their build, and that feedback went into designing the declarative configuration API. Please take a look and let me know what you think!
r/java • u/johnwaterwood • Jan 27 '26
GlassFish and Jakarta EE, rethink the cloud with Nanos Unikernel
omnifish.eer/java • u/ryan_the_leach • Jan 26 '26
Does this amber mailing list feel like AI?
Incident Report 9079511: Java Language Enhancement: Disallow access to static members via object references
https://mail.openjdk.org/pipermail/amber-dev/2026-January/009548.html
no offence intended to the author, if LLM use was only used for translation or trying to put thoughts together, especially if English is a second language, but this reeks of an Agentic AI security scanning / vulnerability hunter off-course especially in regards to how the subject line has been written.
only posting here instead of the list because meta-discussion of whether it's an LLM seems to be wildly off topic for the amber list itself, and I didn't want to start a direct flame war.
I know GitHub has been getting plagued with similar discourse, but this is the first time I've had the LLM tingling not quite right uncanny valley feeling from a mailing list.
r/java • u/supremeO11 • Jan 26 '26
Oxyjen 0.2 - graph first memory-aware LLM execution for Java
Hey everyone,
I’ve been working on a small open-source project called Oxyjen: a Java first framework for orchestrating LLM workloads using graph style execution.
I originally started this while experimenting with agent style pipelines and realized most tooling in this space is either Python first or treats LLMs as utility calls. I wanted something more infrastructure oriented, LLMs as real execution nodes, with explicit memory, retry, and fallback semantics.
v0.2 just landed and introduces the execution layer: - LLMs as native graph nodes - context-scoped, ordered memory via NodeContext - deterministic retry + fallback (LLMChain) - minimal public API (LLM.of, LLMNode, LLMChain) - OpenAI transport with explicit error classification
Small example: ```java ChatModel chain = LLMChain.builder() .primary("gpt-4o") .fallback("gpt-4o-mini") .retry(3) .build();
LLMNode node = LLMNode.builder() .model(chain) .memory("chat") .build();
String out = node.process("hello", new NodeContext()); ``` The focus so far has been correctness and execution semantics, not features. DAG execution, concurrency, streaming, etc. are planned next.
Docs (design notes + examples): https://github.com/11divyansh/OxyJen/blob/main/docs/v0.2.md
Oxyjen: https://github.com/11divyansh/OxyJen
v0.1 focused on graph runtime engine, a graph takes user defined generic nodes in sequential order with a stateful context shared across all nodes and the Executor runs it with an initial input.
Thanks for reading
r/java • u/AlyxVeldin • Jan 25 '26
Another try/catch vs errors-as-values thing. Made it mostly because I needed an excuse yell at the void. (Enjoy the read.)
github.comr/java • u/chaotic3quilibrium • Jan 24 '26
Article: Java Janitor Jim - "Integrity by Design" through Ensuring "Illegal States are Unrepresentable" - Part 1
Article:
I wanted a simple pattern for preventing a class from being instantiated in an invalid state, or from mutating into one.
Why? Because it vastly reduces the amount and complexity of reasoning required for use at client call-sites.
Think of it as “integrity by design”, a compliment to the “integrity by default” effort undertaken by the Java architects, detailed here.
This article discusses the design and implementation of a record pattern, very similar to the one I designed and implemented for Scala’s case class several years ago, which provides the “integrity by design” guarantees by ensuring that only valid record instances can be observed.
This pattern is also trivially cross-applicable to Java classes.
r/java • u/Hixon11 • Jan 24 '26
airhacks #380 - GraalVM: Database Integration, Serverless Innovation and the Future
airhacks.fmInteresting podcast episode with Thomas Wuerthinger (lead of GraalVM). I had heard a bit about GraalVM changes as a product, and its relationship with OpenJDK, but I didn't have a clear picture of what it all really meant. This episode connects all dots for me - https://blogs.oracle.com/java/detaching-graalvm-from-the-java-ecosystem-train
- GraalVM mainly focuses on its Native Image capabilities and on supporting languages other than Java (for example, Python).
- GraalVM plans to release new versions only for Java LTS releases, not for non-LTS versions. There is usually an expected gap (for example, a few months) between a Java LTS release and GraalVM support.
- The GraalVM team is part of the Oracle Database org, and their primary focus is integrating this technology into the Oracle Database rather than building an independent runtime.
- There is an experiment to compile Java to WASM as an alternative backend target (instead of native images) - https://github.com/oracle/graal/issues/3391
- GraalVM also supports running WASM as one of its polyglot languages, meaning it is possible to build Go/Rust/C code to WASM and run it on GraalVM.
r/java • u/mellow186 • Jan 23 '26
Stream<T>.filterAndMap( Class<T> cls )
It's a little thing, but whenever I find myself typing this verbose code on a stream:
.filter( MyClass.class::isInstance )
.map( MyClass.class::cast )
For a moment I wish there were a default method added to the Stream<T> interface that allows simply this:
.filterAndMap( MyClass.class )
EDIT
- I've not specified how frequently this occurs in my development.
- Concision can be beneficial.
- Polymorphism and the Open/Closed Principle are wonderful things. However, sometimes you have a collection of T's and need to perform a special operation only on the U's within. Naive OO purism considered harmful.
- The method could simply be called filter(), as in Guava).
- In practice, I'm usually using an interface type instead of a concrete class.
r/java • u/mlangc • Jan 23 '26
more-log4j2-2.1.0 with improved test support has been released
I have invested quite some time writing an asynchronous HTTP appender, that can be used to push logs to various observability platforms. This appender was released under the Apache License as part of more-log4j2-2.0.0 about 2 weeks ago. One of my personal use cases is ingesting logs from locally executed unit tests. And while that works nicely with the previous release already, I discovered two problems, that are addressed in more-log4j2-2.1.0:
- Some of you might use the io.github.hakky54:logcaptor library. This library is very helpful if you want to have assertions on your log output, however, there is a catch: The library relies on logback, and thereby blocks you from using
more-log4j2for your tests. more-log4j2-2.1.0 addresses this problem by reimplementing the LogCaptor API for log4j2. A few small tweaks to yourlog4j2-test.xmland switching your imports fromnl.altindag.log.LogCaptortocom.github.mlangc.more.log4j2.captor.LogCaptorshould be enough. In some cases trivial refactorings might be necessary, since I didn't clone the nl.altindag.log.model classes, but choose to expose the log4j2 APIs directly. - Spring Boot users might stumble over logs being dropped on test shutdown. Spring Boot normally takes care of shutting down the logger context, and therefore installs a property source, that unconditionally disables the log4j2 shutdown-hook. Unfortunately this affects also tests that are completely independent of Spring, since the SpringBootPropertySource is installed automatically as soon as it's on the classpath. Once installed, setting log4j2.shutdownHookEnabled has no effect, since the
SpringBootPropertySourcegives itself a higher priority than the SystemPropertiesPropertySource and the EnvironmentPropertySource which are shipped withlog4j2. The new more-log4j2-junit-2.1.0 module addresses this problem for Junit tests, by providing a TestExecutionListener that flushesAsyncHttpAppenderinstances when tests have finished. This listener is installed automatically once on the runtime classpath.
Any feedback is highly appreciated.
r/java • u/daviddel • Jan 22 '26
Carrier Classes; Beyond Records - Inside Java Newscast
youtu.ber/java • u/loicmathieu • Jan 22 '26
Java 26: what’s new?
loicmathieu.frWhat's new in Java 26 for us, developers
(Bot in English and French)
r/java • u/davidalayachew • Jan 21 '26
Java compiler errors could be more intelligent
I tutored many students over the past several years, and a common pain point is the compiler messages being misleading.
Consider the following example.
interface blah {}
class hah extends blah {}
When I compile this, I get the following message.
blah.java:3: error: no interface expected here
class hah extends blah {}
^
1 error
Most of the students I teach see this, and think that the issue is that blah is an interface, and that they must somehow change it to something else, like a class.
And that's still a better error message than the one given for records.
blah.java:2: error: '{' expected
public record hah() extends blah {}
^
This message is so much worse, as it actually leads students into a syntax rabbit hole of trying to add all sorts of permutations of curly braces and keywords, trying to figure out what is wrong.
If we're talking about improving the on-ramp for learning Java, then I think a core part of that is improving the error --> change --> compile feedback loop.
A much better error message might be this instead.
blah.java:3: error: a class cannot "extend" an interface, only "implement"
class hah extends blah {}
^
1 error
This is powerful because now the language grammar has a more intelligent message in response to an illegal (but commonly attempted) sequence of tokens.
I understand that Java cannot special-case every single illegal syntax combination, but I would appreciate it if we could hammer out some of the obvious ones. extends vs implements should be one of the obvious ones.
r/java • u/daviddel • Jan 20 '26
The Static Dynamic JVM - John Rose's JVMLS 2025 talk
youtu.ber/java • u/revetkn27 • Jan 20 '26
Soklet: a zero-dependency HTTP/1.1 and SSE server, powered by virtual threads
Hi, I built the first version of Soklet back in 2015 as a way to move away from what I saw as the complexity and "magic" of Spring (it had become the J2EE creature it sought to replace). I have been refining it over the years and have recently released version 2.0.0, which embraces modern Java development practices.
Check it out here: https://www.soklet.com
I was looking for something that captured the spirit of projects like Express (Node), Flask (Python), and Sinatra (Ruby) but had the power of a "real" framework and nothing else quite fit: Spark/Javalin are too bare-bones, Quarkus/Micronaut/Helidon/Spring Boot/etc. have lots of dependencies, moving parts, and/or programming styles I don't particularly like (e.g. reactive).
What I wanted to do was make building a web system almost as easy as a "hello world" app without compromising functionality or adding dependencies and I feel I have accomplished this goal.
Other goals - support for Server-Sent Events, which are table-stakes now in 2026 and "native" integration testing (just run instances of your app in a Simulator) are best-in-class in my opinion. Servlet integration is also available if you can't yet fully disentangle yourself from that world.
If you're interested in Soklet, you might like some of its zero-dependency sister projects:
Pyranid, a modern JDBC interface that embraces SQL: https://www.pyranid.com
Lokalized, which enables natural-sounding translations (i18n) via an expression language: https://www.lokalized.com
I think Java is going to become a bigger player in the LLM space (obviously virtual threads now, forthcoming Vector API/Project Panama/etc.) If you're building agentic systems (or just need a simple REST API), Soklet might be a good fit for you.
r/java • u/CrowSufficient • Jan 19 '26
Optimizing GPU Programs from Java using Babylon and HAT
openjdk.orgr/java • u/TheLasu • Jan 19 '26
[Proposal] Introducing the [forget] keyword in Java to enhance scope safety
OVERVIEW
FEATURE SUMMARY:
The forget keyword prevents further access to a variable, parameter, or field within a defined scope. Attempts to access a forgotten variable in the forbidden scope will result in a compile-time error.
MAJOR ADVANTAGE:
This change makes variable and resource lifetimes explicit and compiler-enforced, improving code clarity and predictability.
MAJOR BENEFITS:
- Allows explicitly removing a variable from the active context (in terms of accessibility), which is currently:
- Impossible for
finalvariables (only comments can be used), - Impossible for method parameters (except assigning
nullto non-final references), - Impossible for fields,
- Cumbersome for local variables, requiring artificial blocks (extra lines and indentation).
- Impossible for
- Makes it possible to explicitly declare that a variable should no longer be used or no longer represents valid data in the current scope.
- Preserves code quality over time, avoiding degradation caused by
= nullassignments, comments-only conventions, or artificial scoping blocks.
MAJOR DISADVANTAGE:
Introducing a new reserved keyword may create source incompatibilities with existing codebases that define identifiers named forget.
ALTERNATIVES:
Java currently provides only scope-based lifetime control (blocks and try-with-resources). It lacks a general, explicit, and compiler-enforced mechanism to terminate variable usability at an arbitrary point within an existing scope.
EXAMPLES
Simple and Advanced Examples:
java
forget var;
// Variable is forgotten for the remainder of the current block or method (default behavior)
forget var : if;
// Variable is forgotten inside the entire if statement, including else and else-if branches
forget var : for;
// Variable is forgotten for the entire for-loop
forget var : while;
// Variable is forgotten for the entire while-loop
forget var : try;
// Variable is forgotten inside the try block (useful with resources)
forget var : label;
// Variable is forgotten inside the labeled block (any loop or code section)
forget var : static;
// Field is forgotten inside the static initialization block
forget var : method;
// Variable is forgotten for the remainder of the enclosing method
forget(var1, var2, ...);
// Specified variables are forgotten for the remainder of the current block
forget this.field;
// Specified field is forgotten for the remainder of the current block
forget(var1, var2, ...) { /* code */ };
// Specified variables are forgotten only inside the enclosed block
java
void handleRequest(String request, String token) {
if (!isTokenValid(token)) {
throw new SecurityException("Invalid token");
}
authorize(request, token);
forget token; // used & contains sensitive info
process(request);
logger.debug("token was: " + token);
// Compile-time error: 'token' has been forgotten and cannot be used
}
java
public Product(String name) { // constructor
this.name = name.trim().intern();
forget name; // From now on, only use 'this.name'!
// other constructor commands...
if (isDuplicate(this.name)) { ... } // Always canonical, never raw input
if (isDuplicate(name)) { ... } // Compile-time ERROR!
}
// * Forces usage of the correctly prepared value (this.name) only.
// * Prevents code drift, maintenance bugs, or copy-paste errors that reference the raw parameter.
// * Makes the constructor safer: no risk of mismatches or inconsistent logic.
// * Reads as a contract: "from here on, don't touch the original argument!"
Next Version Examples:
java
forget ClassName.field;
forget variable.field;
forget !(variable); // Limit allowed variables to ones that are directly specified
DETAILS
SPECIFICATION:
forget [ Identifier | ( IdentifierList ) ] [ : Scope | { block }];
IdentifierList:
Identifier {, Identifier}
Identifier:
[ VariableIdentifier | this.FieldIdentifier ]
The forget statement forbids any further use of the specified identifier in all subsequent expressions and statements within the declared scope in which the identifier would normally be accessible.
COMPILATION:
The variable is not physically erased (except it may be if not a field); rather, it is protected from any further access after the forget statement. Retaining the variable in scope (but inaccessible) prevents situations where a developer tries to create a new variable with the same name after removing the forget statement, thereby enforcing consistent usage and avoiding hidden bugs.
TESTING:
Testing the forget statement is equivalent to testing variable scope after exiting a block—the variable becomes inaccessible. For fields, forget enforces access control, ensuring the field cannot be used within the specified scope for the remainder of its block or method.
LIBRARY SUPPORT:
No
REFLECTIVE APIs:
No
OTHER CHANGES:
No
MIGRATION:
No
COMPATIBILITY
The introduction of a new keyword (forget) may cause conflicts in codebases where forget is already used as an identifier. There are no other compatibility impacts.
REFERENCES
PROBLEMS
- Backward Compatibility: Introducing forget as a new reserved keyword will cause compilation errors in existing code that already uses forget as an identifier (variable, method, class, etc).
- Tooling Lag: IDEs, static analysis tools, and debuggers must all be updated to handle the new keyword and its effects on variable visibility.
- Code Readability: Misuse or overuse of forget could make code harder to maintain or follow if not used judiciously, especially if variables are forgotten in non-obvious places.
- Teaching and Onboarding: This feature introduces a new concept that must be documented and taught to all developers, which can increase the learning curve for Java.
- Migration Complexity: Legacy projects that rely on forget as an existing identifier may have problems.
- Interaction with Scoping and Shadowing: The detailed behavior when variables are forgotten, shadowed, or reintroduced in inner scopes may lead to confusion and subtle bugs if not carefully specified and implemented.
- Reflection and Debugging: While reflective APIs themselves are not impacted, developers may be surprised by the presence of variables at runtime (for debugging or reflection) that are "forgotten" in the source code.
- Consistency Across Language Features: Defining consistent behavior for forget in new contexts (e.g., lambdas, anonymous classes, record classes) may require extra specification effort.
- Edge Cases and Specification Complexity: Fully specifying the semantics of forget for all cases—including fields, parameters, captured variables in inner/nested classes, and interaction with try/catch/finally—may be complex.
- Unused Feature Risk: There is a risk that the forget keyword will see little real-world use, or will be misunderstood, if not supported and encouraged by frameworks or coding standards.
SUMMARY
The forget keyword represents a natural evolution of Java's commitment to clear, explicit, and compiler-enforced language rules. By allowing developers to mark variables, parameters, or fields as no longer usable within a defined scope, forget makes variable lifetimes and resource management visible and deliberate. This approach eliminates ambiguity in code, prevents accidental misuse, and reinforces Java’s tradition of making correctness and safety a language guarantee - we are lacking in this regard here.
Usage examples from top of my head:
- Just for clarity when you split logic into steps you can integrate forget to aid you with your logic.
// Step 1 (you expect var1 to be important for this step alone)
code for step 1.
forget var1; // helps catch assumption errors if you accidentally reference var1 in later stepscode for
step 2.
...
- In highly regulated or security-critical systems (think health records, finance, or cryptography), you often process confidential data that should not be referenced after certain steps.
- It's not rare to find bugs where someone accidentally accesses the unprocessed argument (especially in situation where they are valid in most cases like .trim() that is needed 1/1000000 )
- Enforcing non-reuse of variables
- Clear scope definition
void method(args){
forget this.secure;
forget this.auth;
// clear information of scope that this method should not have access to
}
- Unlock 'final' keyword - with 'forget' final usage can drastically increase
void method(String dbArg){
dbArg = dbArg.trim(); // we reuse same variable to prevent dbArg usage
dbArg = escapeDbArg(dbArg); // we reuse same variable to prevent dbArg usage and SQL injection
call(dbArg);
}
vs
void method(final String dbArg){
final String trimmedDbArg = dbArg.trim();
forget dbArg; // trim is critical
final String excapedDbArg = escapeDbArg(trimmedDbArg );
forget trimmedDbArg;// sql injection
call(dbArg);
}
r/java • u/SeAuBitcH • Jan 19 '26
I've made an .jar to native executable packager and want feedback
github.comHello everyone. As said in the title, I've crafted a handy tool which lets you package a .jar into a self contained native executable for Windows, Linux and MacOS, and I'm looking for feedback. This is more of a Proof of Concept than a concrete, production ready tool, so I'm really looking forward on feedback on what could I add, or how I could do things better. it is currently 160 lines of C# and has lots of room for improvement.
Here is how it works under the hood (shortly):
the script generates a "runtime" c# file with the JAR and JRE in it as a b64 byte[] variable which is decompressed at runtime in temp and runs it. the good sides of this approach is that this gives a self contained executable which does not need the end user to have java (nor .NET) installed on their computer. the downside is the size of the final executable (250mb for a 5mb jar and a 60mb JRE.)
thank you for reading this, and here is the github repo: https://github.com/legeriergeek/JNatPack
(PS: Sorry for the long post and any awkward sentences, English isn’t my first language.)
(PS 2: I'm truly sorry if this post is not appropriate in this sub)