Repository navigation
Releases: juangp3/j2cpp
Release list
J2C Modern Edition 0.6.1 (preview)
Building
- Translating again into the same output directory keeps the build's
objects and libraries, and the files that come out the same keep their
modification time, somake,j2c build,j2c runandj2c test
compile only what changed. A secondj2c runagainst the bundled runtime
compiled all of its 538 files again; it now compiles none. Changing the
compiler or its flags (CXX,CFLAGS) compiles everything again, and
every object now depends on the headers it includes (the stubs, natives
and dependencies did not).
Translation
- An enhanced
forover an array converts each element to the loop
variable's type.for (long v : int[])keptvanint, so shifts and
overflow silently gave wrong results; unboxing (double v : Double[]) and
boxing (Integer v : int[]) did not compile. - An abstract class that inherits the same abstract method from its
superclass and from an interface can call it; the call was ambiguous in
C++. - Translating with
--runtimeand a dependency on the class path no longer
prints JDT's internalStatus ERROR: ... Could not retrieve declared methodslines, which looked like a failure. The output did not change;
one note on stderr now says that JDT logged an internal error.
Extension and agents
- The VS Code extension and the Claude Code plugin have an icon.
- The hint for
J2C-LAMBDA-INTERSECTION-TYPE-VARIABLEnames the safe
rewrite: a generic interface that extends every type of the intersection.
It suggested casting to one functional interface, which drops
Serializableand changes behavior; the agent benchmark caught an agent
following it. The benchmark's scoreboard is indocs/AGENT_BENCHMARK.md.
Requirements
- Java 11 or newer to run the CLI and the VS Code extension.
- A C++20 compiler for generated Makefiles and C++ output.
- VS Code 1.85 or newer for the extension.
Assets
j2c-cli-0.6.1.jar: standalone CLI (java -jar j2c-cli-0.6.1.jar --help).j2c-0.6.1.vsix: VS Code extension with the same CLI bundled
(code --install-extension j2c-0.6.1.vsix).juangp3-j2c-mcp-0.6.1.tgz: the npm package of the MCP server
(npx @juangp3/j2c-mcp), with the same CLI.SHA256SUMS: verify downloads withsha256sum -c SHA256SUMS.
Third-party license notices are in THIRD-PARTY-NOTICES.txt and
licenses/ in the source tree, inside the CLI JAR under
META-INF/j2c-licenses/, and at the root of the VSIX.
J2C Modern Edition 0.6.0 (preview)
First release of J2C Modern Edition: a standalone Java-to-C++ CLI and a VS
Code extension that bundles it, parsing Java 17 source and generating
C++20-targeted output.
Command line and extension
- Standalone CLI with
--sourcepath,--classpath,--name,
--sealed-types advisory|reject,--encoding,--check, and--version. --checklists every compile error and unsupported construct as
file:line: message, with a summary per kind, without writing output.- Translation problems are reported as
file:linediagnostics without a stack
trace. Exit status is 0 on success, 1 for translation problems, and 2 for
invalid arguments. - Source directories skip
module-info.javaandpackage-info.java, which
declare no types; a module declaration no longer fails the check. - Sources are read as UTF-8 by default and generated C++ is always UTF-8,
independent of the platform charset. - VS Code: J2C: Translate to C++ and J2C: Check Translatability in the
editor and Explorer menus. Problems appear in the Problems panel; runs can
be cancelled, and only one runs at a time. - Problems have stable IDs with fix hints (
j2c explain), and--format json
prints machine-readable results with line and column.j2c capabilities
describes supported features and limitations. - Translation refuses to replace a non-empty output directory that J2C did
not create (its contents would be moved to a backup) unless--forceis
given; the extension asks first. - Translation checks every selected file before writing anything, and
reports the problems of all of them at once. A translation that fails
this way leaves the output directory as it was: earlier output is not
moved to the backup, and an empty directory gets no.j2c-outputmarker. - A Java file that is only a dependency (on the source path, not selected)
and does not compile no longer fails the translation: like a library
class, it gets a header and stubs from what the compiler resolved, and no
implementation. The warningJ2C-DEPENDENCY-ERRORS, at its first error,
is printed to stderr and listed inwarningsin JSON. Selected files with
errors still fail.
Runtime (preview)
-
--runtime <directory>translates against a J2C runtime instead of the
running JDK: its Java sources replacejava.*, its C++ natives replace
the generated stubs, and the Makefile builds its hooks. -
The repository's
runtime/is written from the Java SE specification and
covers:String,StringBuilder, the boxed types,MathandObjects;- the exception classes, with Java's uncaught-exception printout and exit
status; - the collections:
ArrayList,LinkedList,ArrayDeque,
PriorityQueue,HashMap,LinkedHashMap,TreeMap, their sets,
Collections,Arrays,Comparatorandjava.util.function; - streams:
Stream,IntStream,LongStream,DoubleStreamand
Collectors, sequential and lazy in the JVM's order, withOptional
and its primitive forms and the summary statistics; String.format,formatted,printfandFormatter, with Java's
rounding and exception messages (no%tdate conversions);java.util.regex(Pattern,Matcher,MatchResult,
PatternSyntaxExceptionwith the JDK's messages), a backtracking
matcher whose stack lives on the heap, used byString.matches,
split,replaceAllandreplaceFirst: classes with intersection,
groups (named, atomic), backreferences, look-around, greedy, reluctant
and possessive quantifiers, and the inline flags.- text input and files:
System.in, thejava.iostreams, readers and
writers (BufferedReader,PrintWriter,FileWriterand the rest),
File,Scanner(whitespace or literal delimiters, no regular
expressions),java.nio.file.FilesandPath, and the UTF-8,
ISO-8859-1 and US-ASCII charsets, with the JVM's buffering, malformed
input handling and exception messages. - threads:
Thread(start, join, sleep, interrupt, names, daemons, the
uncaught-exception handlers and printout),ThreadLocal,
Object.wait,notifyandnotifyAll, andjava.util.concurrent's
atomics,Executors.newFixedThreadPoolwithFuture,
CountDownLatch,ReentrantLockwithCondition,TimeUnitand
ConcurrentHashMap, plusCollections.synchronizedListand
synchronizedMap. Program exit waits for the non-daemon threads.
System.outand the other shared pieces (string interning, class
initialization,Math.random) are thread-safe.
HashMapandHashSetiterate in the JVM's order, so printed maps match. -
--runtime bundleduses the runtime packaged in the CLI JAR, so no
repository checkout is needed (the JAR grows by about 250 KB). It is
extracted on first use into~/.j2c/cache(orJ2C_CACHE_DIR) as
runtime-<version>-<hash>, reused while its files are intact and
replaced when one is missing, changed or added; concurrent processes are
safe. The output equals--runtimewith the checkout'sruntime/.
--runtime <directory>is unchanged, and the CLI still translates
without a runtime by default. Seedocs/RUNTIME.md. -
The MCP tools
j2c_check,j2c_translate,j2c_fix,j2c_report,
j2c_buildandj2c_testtakeruntime("bundled"or a directory),
andj2c buildandj2c testtake--runtime bundled. -
VS Code: the
j2c.runtimesetting,bundledby default, so Check and
Translate use the J2C runtime and translated programs run. This changes
the extension's output:java.*comes from the runtime, so code using JDK
classes it does not provide (such asjava.time) now gets
J2C-COMPILE-ERRORproblems instead of stubs. Setj2c.runtimeto
nonefor the previous behavior, or to a runtime directory. -
The order of includes in generated files no longer depends on the
directory the sources are in (JDT puts it into the keys of generic source
types), so a runtime gives the same output wherever it is. -
j2c reportnames the runtime it compares with as--runtime bundled
when no runtime directory is given. -
make J2C_GC=boehmlinks a program with the Boehm garbage collector,
which then serves every allocation (Java objects and the runtime's C++
containers), so memory is reclaimed. Exceptions in flight stay reachable
whilefinallyblocks run. Threads are registered with the collector;
make testbinaries are not covered. -
CI translates each program in
test/runtime, builds it under
UndefinedBehaviorSanitizer, and compares its output and exit status with
java, then does the same withJ2C_GC=boehm, collecting every 1000
allocations.test/runtime/allocationallocates about 1 GB and must stay
under 100 MB of resident memory with the collector. A program's
input.txtis its standard input, and each run starts in an empty
working directory, so programs can write files. -
synchronizedmethods now hold the monitor ofthis, or of the class
when static; before, the modifier was dropped silently. Asynchronized
block onnullthrowsNullPointerException, and static initializers run
once when several threads reach a class at the same time. Generated
Makefiles build with-pthread. -
Every translation now includes
java.lang.Classand
java.lang.ArrayStoreException, which generated code always uses, and
programs link the program library again after the-extlibrary. -
A lambda or method reference whose types include an inner class of a
parameterized class (Outer<A>.Inner) translates; it was a compile error
because the inner class was written raw. -
A member class of a local or anonymous class that reads a variable the
local class captured translates; translation crashed with a
NullPointerExceptionalthough--checkfound no problems. -
A lambda that J2C reports instead of translating (such as one using
this
of an anonymous class) is no longer also reported, with a runtime, as a
compile error aboutjava.lang.invoke.LambdaMetafactoryat line 1.
Unit tests
--teststranslates JUnit 4 and 5 test classes and generates a GoogleTest
wrapper for each runnable one, with JUnit's lifecycle order (including
inherited methods), skipped disabled tests, and expected exceptions; the
Makefile gainstestsandtesttargets.- With
--tests,--checkreports test features the wrappers cannot run
(mocking libraries, runners and extensions, parameterized or repeated tests,
@Nested, timeouts,@TestInstance, private or parameterized methods).
JUnit 4's@Test(timeout = ...)is reported too (it was missed when the
timeout was written as anint). - JUnit assertions and assumptions (
assertEqualswith and without delta,
assertTrue,assertNull,assertSame,assertArrayEquals,fail,
assertThrows,assertDoesNotThrow,assumeTrue, and others) are
translated into helpers that follow JUnit's rules and messages without a
Java runtime. Other assertion forms are reported. Comparing JDK objects
and showing custom messages need the runtime. - With
--runtime, translated tests compare JDK objects (strings, boxed
numbers, lists, maps) with Java'sequals, and failure messages match
JUnit's: values shown withtoString, JUnit 5'smessage ==>prefix,
Supplier<String>messages called only on failure, and JUnit 4's own
forms (expected:<a> but was:<b>, strings compacted as
ComparisonFailuredoes, itsassertNull,assertSame,assertNotEquals
and array messages). TheAssertionErrorcarries the message, and
GoogleTest reports every exception's message. JUnit 4's assertions now
translate intoj2c::junit::junit4helpers. - JUnit 4's
@Test(expected = ...)failures use JUnit's messages
(`Expected ...