j2objc Documentation

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

6,034 stars Java Java 1 file ยท ~3,324 tokens
RAW Doc

Technical Documentation: google/j2objc

โ„น๏ธ Provenance: Multi-Tier Ingestion ยท CodeWiki Reference

Overview (`README.md`)

J2ObjC: Java to Objective-C Translator and Runtime

Project site: https://j2objc.org
J2ObjC blog: https://j2objc.blogspot.com
Questions and discussion: https://groups.google.com/group/j2objc-discuss

What J2ObjC Is

J2ObjC is an open-source command-line tool from Google that translates
Java source code to Objective-C for the iOS (iPhone/iPad) platform. This tool
enables Java source to be part of an iOS application's build, as no editing
of the generated files is necessary. The goal is to write an app's non-UI
code (such as application logic and data models) in Java, which is then
shared by web apps (using GWT), Android apps,
and iOS apps.

J2ObjC supports most Java language and runtime features required by
client-side application developers, including exceptions, inner and
anonymous classes, generic types, threads and reflection. JUnit test
translation and execution is also supported.

J2ObjC is currently beta quality. Several Google projects rely on it, but
when new projects first start working with it, they usually find new bugs
to be fixed. If you run into issues with your project, please report them!

What J2ObjC isn't

J2ObjC does not provide any sort of platform-independent UI toolkit, nor are
there any plans to do so in the future. We believe that iOS UI code needs to
be written in Objective-C, Objective-C++ or Swift using Apple's iOS SDK (Android
UIs using Android's API, web app UIs using GWT, etc.).

J2ObjC cannot convert Android binary applications. Developers must have source
code for their Android app, which they either own or are licensed to use.

Requirements

  • JDK 21
  • Mac workstation or laptop
  • OS X 15.6.1 or higher
  • Xcode 16.3 or higher

License

This 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. See its
README and
LICENSE.

Running on GNU/Linux

To build and run on GNU/Linux, install the Darling project, then following its Compile and Run a Program example. Please note that j2objc is only supported on iOS/macOS.

Artifact Signatures

This project publishes some artifacts through Maven Central with a groupId of com.google.j2objc.
These artifacts are currently signed with [the following PGP/GPG key]
(https://keyserver.ubuntu.com/pks/lookup?op=get&search=0xC3259D20DAEC4ACE6D57CC83340B090F727518D8):

text
---------
pub   ed25519 2025-08-13 [SC] [expires: 2028-08-12]
      C3259D20DAEC4ACE6D57CC83340B090F727518D8
uid           [ultimate] Thomas Ball <[email protected]>
sub   cv25519 2025-08-13 [E] [expires: 2028-08-12]

Older artifacts are signed with the following PGP/GPG keys:

text
pub   rsa2048 2023-01-10 [SC] [expires: 2025-01-09]
      EB1B3DE71713C9EC2E87CC26EE92349AD86DE446
uid           [ unknown] Thomas Ball <[email protected]>
sub   rsa2048 2023-01-10 [E] [expires: 2025-01-09]
text
pub   rsa2048 2015-09-25 [SC]
      B801E2F8EF035068EC1139CC29579F18FA8FD93B
uid           [ unknown] Tom Ball <[email protected]>
sub   rsa2048 2015-09-25 [E]

Overview (`tree_shaker/README.md`)

J2ObjC Tree Shaker

About:
The tree shaker project is an experimental tool in the J2ObjC family that lets
users detect any unused code in their Java program. The purpose of the tool is
to provide the translator with a list of unused elements in the code that it
can remove to reduce the size of the translated project.

Usage:
The tree shaker can be used in two ways:

  1. Manual Analysis: Using the tree shaker by itself on a package of source
    files, it will report a set of classes and methods that it detected as unused.
  2. Dead Code Elimination in Translator: The tree-shaker-report output file,
    generated by the tree shaker, can be used as an input to the translator, using
    its Dead Code Elimination functionality (see the docs for translator). This
    will automatically remove the unused code reported by the tree shaker from the
    final translated source code.

Running Tree Shaker:
The tree shaker command takes in a few flags, as seen in the help message:

text
Usage: tree_shaker <options> <source files>
where possible options include:
  -sourcepath <path>           Specify where to find input source files.
  -classpath <path>            Specify where to find user class files.
  --tree-shaker-roots          Specify a file that lists the public root classes and methods.
  -s, --sourcefilelist <file>  Specify a file that lists the source files to be analyzed.
  -encoding <encoding>         Specify character encoding used by source files
  -Xbootclasspath:<path>       Boot path used to compile the input sources. (not the tool itself)
  -version                     Version information
  -Werror                      Treats all warning as errors.
  -h, --help                   Print this message.

All elements in the input source files that can be reached from the public
roots will be kept, and the others marked as unused. The input file formatting
for classes is the full packageName.className for the class, one class per line:

text
# These are the root classes for this library:
foo.bar.Mumble
itsy.bitsy.Spider

# Inner-classes work, too:
twisty.little.Passage.Direction

When indicating a class as a public root, the tree shaker will take all public
methods inside that class and add them to the public root set, for convenience.
To add specific methods to the public root set, add their enclosing class's
packageName.className, followed by a colon, and all of the root set methods
inside that class on the following lines, one on each line, preceded by 4
spaces. For example, this tells tree_shaker to only mark the main method as
used, which allows other methods to potentially be reported as dead:

text
my.little.Pony:
    main(java.lang.String[])

Ending Note:
The tree shaker tool is an experimental project, used at the user's own risk.
The manual analysis use case is completely safe, and is the recommended way to
analyze source code for unused elements while the tree shaker is still in
testing. More adventurous users are encouraged to experiment with dead code
elimination, find and/or fix bugs, and submit pull requests.


Overview (`jre_emul/junit_tests/README.md`)

JRE JUnit Tests

This is a simple iOS app that redirects System.out and System.err to a
scrollable panel, then runs the JUnit tests for the
J2ObjC's JRE library as a background task. Test output is also saved as
a file on the iOS device, which can be uploaded from Xcode's Organizer
window.

App Icons

The project's app icons for this app were created using
GIMP for Mac OS X, then converted into iOS
icons using the Macappicon app icon generator. To
update the icons to the lastest iOS requirements, drag the junit-tests-logo.png
file to MakeAppIcon's toaster, enter your email when it's created the icon set
and it will be mailed to your account. Unzip the icon set and copy
ios/AppIcon.appiconset to j2objc/jre_emul/junit_tests/Images.xcassets/.

Reuse and Improve

Feel free to clone this app and change it to run your app's JUnit tests.
We're also very interested in any improvements that would help make testing
easier.


Overview (`jre_emul/android/platform/external/okhttp/okio/README.md`)

Okio

Okio is a new library that complements java.io and java.nio to make it much
easier to access, store, and process your data.

ByteStrings and Buffers

Okio is built around two types that pack a lot of capability into a
straightforward API:

  • ByteString is an immutable sequence of bytes. For character data, String
    is fundamental. ByteString is String's long-lost brother, making it easy to
    treat binary data as a value. This class is ergonomic: it knows how to encode
    and decode itself as hex, base64, and UTF-8.

  • Buffer is a mutable sequence of bytes. Like ArrayList, you don't need
    to size your buffer in advance. You read and write buffers as a queue: write
    data to the end and read it from the front. There's no obligation to manage
    positions, limits, or capacities.

Internally, ByteString and Buffer do some clever things to save CPU and
memory. If you encode a UTF-8 string as a ByteString, it caches a reference to
that string so that if you decode it later, there's no work to do.

Buffer is implemented as a linked list of segments. When you move data from
one buffer to another, it reassigns ownership of the segments rather than
copying the data across. This approach is particularly helpful for multithreaded
programs: a thread that talks to the network can exchange data with a worker
thread without any copying or ceremony.

Sources and Sinks

An elegant part of the java.io design is how streams can be layered for
transformations like encryption and compression. Okio includes its own stream
types called Source and Sink that work like InputStream and
OutputStream, but with some key differences:

  • Timeouts. The streams provide access to the timeouts of the underlying
    I/O mechanism. Unlike the java.io socket streams, both read() and
    write() calls honor timeouts.

  • Easy to implement. Source declares three methods: read(), close(),
    and timeout(). There are no hazards like available() or single-byte reads
    that cause correctness and performance surprises.

  • Easy to use. Although implementations of Source and Sink have only
    three methods to write, callers are given a rich API with the
    BufferedSource and BufferedSink interfaces. These interfaces give you
    everything you need in one place.

  • No artificial distinction between byte streams and char streams. It's all
    data. Read and write it as bytes, UTF-8 strings, big-endian 32-bit integers,
    little-endian shorts; whatever you want. No more InputStreamReader!

  • Easy to test. The Buffer class implements both BufferedSource and
    BufferedSink so your test code is simple and clear.

Sources and sinks interoperate with InputStream and OutputStream. You can
view any Source as an InputStream, and you can view any InputStream as a
Source. Similarly for Sink and OutputStream.

Dependable

Okio started as a component of OkHttp, the capable HTTP+SPDY client
included in Android. It's well-exercised and ready to solve new problems.

Example: a PNG decoder

Decoding the chunks of a PNG file demonstrates Okio in practice.

java
private static final ByteString PNG_HEADER = ByteString.decodeHex("89504e470d0a1a0a");

public void decodePng(InputStream in) throws IOException {
  BufferedSource pngSource = Okio.buffer(Okio.source(in));

  ByteString header = pngSource.readByteString(PNG_HEADER.size());
  if (!header.equals(PNG_HEADER)) {
    throw new IOException("Not a PNG.");
  }

  while (true) {
    Buffer chunk = new Buffer();

    // Each chunk is a length, type, data, and CRC offset.
    int length = pngSource.readInt();
    String type = pngSource.readUtf8(4);
    pngSource.readFully(chunk, length);
    int crc = pngSource.readInt();

    decodeChunk(type, chunk);
    if (type.equals("IEND")) break;
  }

  pngSource.close();
}

private void decodeChunk(String type, Buffer chunk) {
  if (type.equals("IHDR")) {
    int width = chunk.readInt();
    int height = chunk.readInt();
    System.out.printf("%08x: %s %d x %d%n", chunk.size(), type, width, height);
  } else {
    System.out.printf("%08x: %s%n", chunk.size(), type);
  }
}

Download

Download the latest JAR or grab via Maven:

xml
<dependency>
    <groupId>com.squareup.okio</groupId>
    <artifactId>okio</artifactId>
    <version>1.6.0</version>
</dependency>

or Gradle:

groovy
compile 'com.squareup.okio:okio:1.6.0'

Snapshots of the development version are available in Sonatype's snapshots repository.


--- METRICS ---