On Fri, Sep 23, 2016 at 4:55 PM, Terasgr <
tera...@gmail.com> wrote:
> Hello brave Avian team!
>
> I have a few questions (and suggestions) for Avian & especially the iOS
> port, and I’d like to discuss the with you, if you wish.
>
> First of all, I believe that the option
> -framework Carbon
> is not valid for an iOS application at all. It might be used for (older) SWT
> implementation, but not even for that any more (now SWT is supposed to use
> Cocoa).
> Btw, the binary SWT demos of Avian do not work any more at all, in OSX,
> probably exactly due to this missing Carbon library from the OS? Or because
> they start in the main thread witch is now deprecated and should run in
> another thread?
I agree that Carbon never made sense for iOS, and would not be
surprised if it's no longer supported on MacOS. Not sure why the demo
apps aren't working, but I'll debug that when I have time.
> Another thing is that I think the options:
> -fobjc-abi-version=2 -fobjc-legacy-dispatch
> and
> -Xlinker -objc_abi_version -Xlinker 2
> are not needed any more. It might be needed in (very) old versions of the
> simulator but now I have the feeling that they are not.
You're probably right. I can't remember what those flags are for,
anyway, and if hello-ios.git still builds and runs okay without them
we might as well remove them.
> A third thing, rather trivial, but a bit not-expected. It has to do with
> core Avian itself.
> When compiling avian with the options
> make platform=ios arch=arm64 process=compile mode=fast bootimage=true
> under the build directory it is found the "ios-arm64-bootimage” folder
> (which is expected) and the "macosx-x86_64-interpret” which is not expected.
> When creating the bootimage, bootimage-generator requests the “libjvm.dylib”
> file found there with the “-hostvm" parameter. I have no knowledge what
> actually this parameter does, but it seems a bit strange to link a mac dylib
> with an arm64 executable. Things get more tricky, because indeed lambda
> functions seem to properly work (as expected) on an actual iPhone device.
This is because the bootimage-generator executable, which is
responsible for AOT-compiling Java bytecode, needs to actually run
some Java code in order to compile any invokedynamic-based lambda
expressions it encounters. This was a design choice I made because I
had already written the needed code in Java and didn't want to rewrite
(and maintain) it in C++ as well. So the makefile builds a minimal
JVM for the native platform (macosx in this case) so it can run that
Java code while generating the bootimage. It can't use the system JVM
(e.g. HotSpot) for this purpose, because the Java code in this case is
closely tied to Avian's internals.
Anyway, yes, it's complicated, but it saved us from duplicating a
bunch of code between Java and C++. If this causes a lot of pain for
you, we could discuss alternatives, but that's the way it works now.
> I am also trying to optimise the procedure, compile Avian only once and use
> it multiple times when compiling an iOS project.
> It seems that 4 files are required:
> a) bootimage-generator
> b) classpath.jar
> c) libavian.a
> d) libjvm.dylib
>
> From what I understand is, that I need (a) and (c) in all architectures (sim
> i386, sim x86_64, arm, and arm64), while (b) and (d) only once.
> Am I correct or I am missing something?
That seems correct to me. Josh has done some work to allow the
bytecode-to-machine-code compiler target more than one architecture in
a single build, which would allow you to build just one instance of
(a) and (c), but I don't think that project was ever entirely
finished. Josh can correct me if I'm wrong about that.
> PS:
>
> The main reason of my interest is that, I am the core developer of a
> multi-platform development environment for mobile devices, which make
> possible to compile true cross-platform applications, including the native
> GUI based on iOS libraries, in Java, for iOS, Android and Desktop. (
>
http://crossmobile.tech if you are curious - we haven’t really released it
> openly yet, only for our own internal projects)
>
> Right now we are using XMLVM Objective C backend (which in the past I was an
> active contributor).
> Unfortunately now XMLVM has started to show its age, and we are considering
> to use alternative methods instead. Avian seemed to me the best alternative
> and I am trying to dive deeply in its guts to see its limits.
>
> The main requirement for us would be a direct way to connect Objective C
> objects with Java objects. Since I haven’t seen such an approach in the
> demos, I was thinking to ask you about it. I was thinking to keep a pointer
> reference of the allocated Objective C object inside the Java object (as
> long number) and call the release method on the finalize() method of the
> Java object. And -of course- I need to find a clever way to instantiate
> Objective C objects from Java objects and Java objects from Objective C
> objects (XMLVM performs a similar mapping but I am afraid is not directly
> applicable with Avian).
>
> What do you think about this approach? Do you have any better ideas? Or is
> there any example that I missed (even for pure C memory allocations or C++
> objects) ?
Using finalize() is almost never a good idea in my opinion. Avian
collects garbage generationally, meaning objects which reach the
tenure stage can remain resident long after the last references to
them have been eliminated. Since the VM can't "see" the space taken
up by the corresponding Objective C objects, nor do those objects put
any pressure on the Java heap, it has no urgency to collect and
finalize the objects which reference them. For the same reason, it's
almost always a bad idea to rely on finalize() to clean up e.g. open
file descriptors, OS handles, and other limited resources that have no
direct relationship to the Java heap; the VM doesn't know (and
shouldn't be expected to know) those resources need to be cleaned up
promptly even when there's no other reason to run a GC cycle.
Anyway, to answer your question there isn't any example of a clever
way to tie Objective-C objects to Java objects. In all the
Avian-on-iOS projects I've worked on, we generally kept the Java and
Objective-C components of our apps separate and let them communicate
via a language-agnostic protocol like Protocol Buffers, almost as if
they were separate processes. In the cases where the Java code needed
to refer directly to an Objective-C object, we used a long to store
the pointer like you mentioned, but also made sure to explicitly
release that pointer when we were done with it rather than rely on
finalize() to release it in some indeterminate future.
Unfortunately, Java-style garbage collection doesn't pair well with
reference counting, at least not if you expect references counts to be
decremented promptly or predictably. On the other hand, if you don't
care about promptness or predictability, finalize() might be a
solution, but I would recommend phantom references over finalize()
since it gives you more control, e.g. over which thread the release
call is made from.
XMLVM and j2objc are better at this since they translate Java code to
Objective-C code and (I assume) rely inherently on reference counting
rather than traditional Java-style GC.
Hope that helps clarify things.