@J2ObjCIncompatible annotation limitations

107 views
Skip to first unread message

Simone Sergi

unread,
Mar 15, 2021, 6:49:38 PM3/15/21
to j2objc-discuss
Hi all,
in the Android app I'm trying to transpile I've a class where I want to skip part of the code (because it depends on core Android classes, so it actually cannot be translated, and in any case I will not need it).

I've found the @J2ObjCIncompatible annotation on the documentation, I've tried it to remove, i.e., the code of an entire class and it works well. However, in that specific case, I need to skip a static final variable creation + initialization and this seems not to work.

So, with examples:
In this case the annotation seems to work

@J2ObjCIncompatible
public class MyContract {
[...]
}

While in this other no, the code is always transpiled

@J2ObjCIncompatible
public static final Uri BASE_CONTENT_URI = Uri.parse("content://" + CONTENT_AUTHORITY);


What I'm missing / misunderstanding here?

Thank you very much!
Simone

Tom Ball

unread,
Mar 15, 2021, 7:21:14 PM3/15/21
to j2objc-...@googlegroups.com
It’s likely a bug. Please file an issue and you’ll be notified when it’s fixed. 

--
You received this message because you are subscribed to the Google Groups "j2objc-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to j2objc-discus...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/j2objc-discuss/36eb7f49-6df6-4257-9c38-b0ddb9712775n%40googlegroups.com.

Tom Ball

unread,
Mar 15, 2021, 8:14:26 PM3/15/21
to j2objc-discuss
Actually, it works with this test class (I used a similar pattern since Uri appears to be one of your project's classes):

import java.util.regex.Pattern;

public class MyContract {
  @com.google.j2objc.annotations.J2ObjCIncompatible
  public static final Pattern ANDROID_ONLY_PATTERN = Pattern.compile(".*");
}

The above generates files without ANDROID_ONLY_PATTERN, and with when the annotation is commented out.

Can you come up with a simple example that we can build that demonstrates the problem?

Simone Sergi

unread,
Mar 16, 2021, 2:39:32 PM3/16/21
to j2objc-discuss

Hi Tom,
Sorry for my late reply but it takes quite a long time to find a minimal test case that reproduces my error.
Actually, your class compile fine and I’ve discovered that also mine works well if transpiled alone. Instead I experience this strange behavior only when the classes become 2.

Probably I’m missing something very stupid…here is a dummy minimal example

Case 1:
Just one minimal class where I use @J2ObjCIncompatible to avoid transpile a var. This one, as stated, works well

==========
import com.google.j2objc.annotations.J2ObjCIncompatible;
import android.net.Uri;

public class POIContract {

    @J2ObjCIncompatible
    public static final Uri BASE_CONTENT_URI = Uri.parse("content://" + "DUMMY-DUMMY");

    public static final String TABLE_NAME="myTable";
}
==========

Case 2:
I add another file with another class in the same package that simply uses the TABLE_NAME var

==========
public class POIDbHelperGeneric {
    static final String SQL_CREATE_LOCATION_TABLE = "CREATE TABLE " + POIContract.TABLE_NAME;   
}
==========

If I try to compile both I got the error related to the unknown android.net.Uri class. But actually, the strangest thing is that the error is thrown when processing the second class. (So, processing POIDbHelperGeneric.java but the error is thrown on POIContract.java)
This the full error:

Mar 16, 2021 6:28:47 PM com.google.devtools.j2objc.pipeline.GenerationBatch processSourceFile
FINEST: processing /Users/simo/Desktop/XCodeProjects/J2OBJCBase-test-rw2/it/xxxxx/app/data/POIDbHelperGeneric.java
Mar 16, 2021 6:28:48 PM com.google.devtools.j2objc.pipeline.FileProcessor processBatch
FINEST: Processing batch of size 1
error: ./it/xxxxx/app/data/POIContract.java:10: cannot find symbol
  symbol:   method parse(java.lang.String)
  location: class android.net.Uri
Command RuleScriptExecution emitted errors but did not return a nonzero exit code to indicate failure

I’m sorry but I cannot understand what’s wrong…
Hope it is a trivial mistake ;)

Simone

Tom Ball

unread,
Mar 16, 2021, 4:59:25 PM3/16/21
to j2objc-discuss
I think the issue is that the j2objc runtime only supports a very small set of utility Android classes, and android.net.Uri isn't one of them. Uri would be difficult to port, as it depends upon Parcelable, which is very specific to Android. StackOverflow has an answer you might be able to use instead.

The reason behind this is that j2objc doesn't translate Android code, it translates platform-independent Java code, no pretty much any android.* imports will fail. Teams with large apps design their apps so that the platform-specific requirements are hidden behind interfaces, which shared code uses and for which separate implementations for each platform are created. Because of this, j2objc doesn't offer much value for small apps (they're largely platform-specific code).

Simone Sergi

unread,
Mar 16, 2021, 5:13:23 PM3/16/21
to j2objc-discuss
Thank you again for your answer,
but so probably I've misunderstand what the @J2ObjCIncompatible annotation is for:
Actually what I want is just to avoid using the android.net.Uri class. I use it in my Android app but I do not need it at all on the ios side, and so I've modified my code adding that annotation as


    @J2ObjCIncompatible
    public static final Uri BASE_CONTENT_URI = Uri.parse("content://" + "DUMMY-DUMMY");

That's the portion of code I do not need.
What I do not understand is why this code is (tryed to be) compiled even if it is annotated as incompatible (and never used)...

Regards
Simone

Tom Ball

unread,
Mar 16, 2021, 8:25:02 PM3/16/21
to j2objc-discuss
Okay, I suspect the problem is that Uri isn’t resolved, since the error is:

cannot find symbol
  symbol:   method parse(java.lang.String)
  location: class android.net.Uri

That’s not a source file, it’s not on the sourcepath and it’s not on the classpath, so javac (j2objc’s front end) failed before j2objc started translating. So I suggest creating a stub file for android.net.URI, which doesn't need any code, just the class definition and the definitions of its methods you use. Here's an example. That will allow javac to resolve the symbol, so that j2objc can then discard it.

Simone Sergi

unread,
Mar 17, 2021, 7:30:29 AM3/17/21
to j2objc-discuss
Hi,
this sounds absolutely possible.
Actually I've made another couple of tests and defining only the Uri class is not enough. The error is related to the parse method, not only to the Uri class itself. So, the only way I've found to solve is to define also a "fake" parse function.
 
=======
package android.net;
public class Uri {
    public static Uri parse(String in){ return null; }
}
=======

With this I can compile.

But so my question become philosophical: 
If I define all the fake methods I need, I can also remove the J2ObjCIncompatible annotation, it compile in any case. On the other hand, I'll have to define a number of fake methods used just as placeholder at compilation time.
But so, what si the benefit of @J2ObjCIncompatible ?

Bye
Simone

Tom Ball

unread,
Mar 17, 2021, 12:41:22 PM3/17/21
to j2objc-discuss
Discussing philosophy with an Italian? I am certain to lose. :-)

J2ObjC does not have some grand design, it's a Java compiler and runtime for iOS that is driven by requests by other engineering teams. Here, the request for J2ObjCIncompatible came from Google Guava, our open-source, cross-platform Java utility library. Searching that repository for J2ObjCIncompatible finds thirteen places it's used, and the comments next to the annotations briefly describe why they're needed. And you can see why they asked for this annotation, since they used a similar one to support GWT.

Simone Sergi

unread,
Mar 17, 2021, 4:53:46 PM3/17/21
to j2objc-discuss
Actually I'm an engineer too so
- my philosophy will be terribly low-profile ;)
- I agree that some example are more explicative that big theories
I'll have a look at these.
Thank you very much for the patience and especially for this great tool!

Bye
Simone
Reply all
Reply to author
Forward
0 new messages