CLI tool
google/j2objc avatar
google/j2objc

J2ObjC: Sharing Java Logic With an iOS App Without Rewriting It

A Java to iOS Objective-C translation tool and runtime.

6,038 stars999 forksJavaNOASSERTION

At a glance

What is it?
J2ObjC is Google's command-line translator that turns Java source into Objective-C for iOS, so non-UI code can be shared across Android, web and Apple builds. It is beta quality, macOS-only, and depends on a specific JDK and Xcode toolchain.
Who is it for?
J2ObjC fits teams that already own Java source for their app logic and want that same code compiled into an iOS build without editing generated files. It does not fit anyone looking for a cross-platform UI toolkit, anyone without Android or Java source to translate, or anyone building on Linux, since the README states j2objc is only supported on iOS/macOS and GNU/Linux requires the Darling project.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Java, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem J2ObjC solves: one Java codebase, three platforms

Most cross-platform mobile strategies ask you to give something up. Either you write the shared layer in a language neither platform natively consumes, or you maintain parallel implementations of the same business rules in Java and Objective-C. J2ObjC takes a third route. The README describes the goal plainly: write an app's non-UI code, such as application logic and data models, in Java, then share it across web apps using GWT, Android apps, and iOS apps. The translator emits Objective-C that slots into an iOS build, and the README states that no editing of the generated files is necessary. That last clause is the whole point. Generated output is a build artifact, not a source tree you hand-maintain.

The audience is narrow and specific. You need Java source you own or are licensed to use, because the README states J2ObjC cannot convert Android binary applications. You need a Mac, since the requirements list a Mac workstation or laptop. And you need to accept that the UI stays native: the README is blunt that J2ObjC provides no platform-independent UI toolkit and that there are no plans to add one. If your pitch for a cross-platform framework is 'write the screens once', this is not that tool and will not become that tool.

How the translator and runtime fit together

The repository is split into a translator and a set of runtime libraries. The translator/ directory holds the Java-to-Objective-C compiler. The jre_emul/ directory holds the emulation of the Java runtime that the generated code links against, because Objective-C has no java.lang, no java.util collections and no exception model that matches Java's. The remaining top-level entries map to the rest of the surface: guava/, junit/, jsr305/, inject/, protobuf/, xalan/, testing/mockito/ and testing/truth/ are ports of the libraries Java code typically imports. The Makefile confirms this shape: the frameworks target descends into jre_emul, junit, jsr305, inject/javax_inject, guava, testing/mockito, testing/truth and xalan, building each as a framework.

The README lists what the translator handles: exceptions, inner and anonymous classes, generic types, threads and reflection, plus JUnit test translation and execution. Those are not incidental features. Reflection and threads are the two areas where a source-to-source translator usually breaks down, because both depend on runtime metadata that a naive translation would discard. Supporting them is why jre_emul exists as a substantial component rather than a thin shim.

The Makefile also tells you how the project expects to be consumed. Its header comment says the Makefile's purpose is as a subproject in an Xcode project. The build is not a standalone binary you install once and forget; it is designed to be driven from inside the iOS build that consumes its output.

Installing J2ObjC and translating a first class

The hard requirements come first, and they are not negotiable: JDK 21, a Mac, OS X 15.6.1 or higher, and Xcode 16.3 or higher. The README points to the project site at j2objc.org and the INSTALL file at the repository root for setup instructions, and notes that GNU/Linux is only usable through the Darling project, with the caveat that j2objc is only supported on iOS/macOS.

Build the distribution from the repository root. The default Makefile target is dist, so a bare make runs it:

bash
make dist

The Makefile defines dist as depending on print_environment, translator_dist and jre, so this step compiles the translator and the runtime before producing a distribution directory. The Makefile references a DIST_DIR variable, and man pages are installed under $(DIST_DIR)/man/man1, so the distribution tree is where the built artifacts land.

Once the distribution exists, translation is a command-line step. The repository ships ready-made examples under examples/, including Hello, HelloSwift, Contacts and protobuf, which is the fastest way to see the expected input and output layout rather than guessing at flags. For a real project, the practical pattern is to keep Java sources in their own directory, run the translator over that directory as part of the build, and then add the generated Objective-C to the Xcode target alongside the runtime frameworks. The Makefile's frameworks target is what produces those frameworks:

bash
make frameworks

That target builds jre_emul, junit, jsr305, inject/javax_inject, guava, testing/mockito, testing/truth and xalan as frameworks. If your shared code uses protocol buffers, all_frameworks extends this with protobuf_dist and the protobuf runtime framework.

Where J2ObjC breaks down or is the wrong choice

The README itself sets the first expectation: J2ObjC is currently beta quality, and while several Google projects rely on it, new projects usually find new bugs to be fixed. That is an unusually direct statement from a project owner, and it should shape how you plan. Treat the translator as a dependency with a defect tail, not as a finished compiler.

The platform constraint is the second hard boundary. The README states plainly that j2objc is only supported on iOS/macOS. The GNU/Linux path runs through the Darling project, and the README frames it as a way to build and run rather than a supported target. If your CI runs on Linux containers, that is a real architectural problem, not a configuration detail.

The third boundary is scope. J2ObjC does not translate Android binaries, so if you inherited an APK and no sources, the tool has nothing to work with. And it deliberately stops at the UI layer. A team hoping to share screen code between Android and iOS will find the README closing that door explicitly. The honest framing is that J2ObjC shares logic, and logic only. The moment your shared code wants to touch a view hierarchy, you are back to writing platform code in Objective-C, Objective-C++ or Swift against Apple's SDK.

J2ObjC against J2CL and hand-written bindings

The closest comparison in the related searches is J2CL, Google's other Java-to-something compiler, which targets JavaScript rather than Objective-C. The difference in approach matters more than the difference in output language. J2CL produces JavaScript for browsers, where the runtime is the browser itself and the deployment target is a web page. J2ObjC produces Objective-C for iOS, where the output must link against Apple's frameworks and be compiled by Xcode with a real device toolchain. That means J2ObjC carries a heavier requirement set: a Mac, a specific Xcode version and a JDK, none of which a browser-targeting compiler needs.

The other alternative is not a tool at all. You can write the shared logic twice, once in Java for Android and once in Objective-C or Swift for iOS, or expose it through a service and call it over the network. Duplicating logic keeps full control over both implementations and avoids a generated-code layer entirely, at the cost of maintaining two copies of every rule and every bug fix. A network boundary avoids duplication but adds latency and a failure mode where the app stops working offline. J2ObjC sits between those options: one source of truth, compiled ahead of time, with the generated code checked into the build rather than shipped as a separate service.

Maintenance, licensing and the cost of staying current

The repository is not archived, and the last push was on 2026-09-18, days before this writing. The most recent release listed is 3.1, dated 2025-08-14. Whatever the beta label says about feature completeness, the project is receiving commits.

Upgrade cost concentrates in the toolchain requirements. The README pins JDK 21, OS X 15.6.1 or higher, and Xcode 16.3 or higher. Those are moving targets on Apple's side, so an Xcode upgrade can force a J2ObjC upgrade, which can change generated output. The repository includes cycle_finder/ and tree_shaker/, two tools that suggest generated-code size and dependency cycles are active concerns for large codebases. Plan for regenerating and re-verifying output whenever you move either the JDK or Xcode.

On licensing, the README states the library is distributed under the Apache 2.0 license found in the LICENSE file. The protocol buffers library is distributed under the same BSD license as Google's protocol buffers, with its own README and LICENSE. Artifacts published to Maven Central under the groupId com.google.j2objc are signed, and the README lists the current PGP key fingerprint along with two older keys used for earlier artifacts. If you consume those artifacts, verify signatures against the listed keys rather than assuming any single key covers the whole history. This is a description of what the repository states, not legal advice; review the LICENSE file yourself for your own use case.

Editorial conclusion

J2ObjC fits teams that already own Java source for their app logic and want that same code compiled into an iOS build without editing generated files. It does not fit anyone looking for a cross-platform UI toolkit, anyone without Android or Java source to translate, or anyone building on Linux, since the README states j2objc is only supported on iOS/macOS and GNU/Linux requires the Darling project. Before committing, verify that your code stays inside the supported feature set (exceptions, inner and anonymous classes, generics, threads, reflection) and check the 3.1 release notes for behaviour changes that affect your build.

Frequently asked questions

What is J2ObjC used for?

It translates Java source code to Objective-C for iOS, so an app's non-UI code such as application logic and data models can be written once in Java and shared by web, Android and iOS builds. The README states that no editing of the generated files is necessary.

What are the requirements to build J2ObjC?

The README lists JDK 21, a Mac workstation or laptop, OS X 15.6.1 or higher, and Xcode 16.3 or higher. It also notes that j2objc is only supported on iOS/macOS, with GNU/Linux requiring the Darling project.

Does J2ObjC provide a cross-platform UI toolkit?

No. The README states that J2ObjC does not provide any sort of platform-independent UI toolkit and that there are no plans to do so, because iOS UI code should be written with Apple's iOS SDK.

Can J2ObjC convert an Android app binary?

No. The README states that J2ObjC cannot convert Android binary applications, and that developers must have source code for their Android app which they either own or are licensed to use.

What license is J2ObjC distributed under?

The README states the library is distributed under the Apache 2.0 license found in the LICENSE file, while the protocol buffers library is distributed under the same BSD license as Google's protocol buffers.

Official sources

  1. google/j2objc on GitHub
  2. Issues
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/google-j2objc.svg)](https://hysenlabs.com/projects/google-j2objc)