Skip to content

Using JPL with Java 8 on Mac OS X issues #2

Description

@pmoura

On Mac OS X there is a command, java_home, that returns the path for the user's enabled and preferred JVMs in the Java Preferences application. This command is Apple's advised way of defining the JAVA_HOME environment variable. On my system I get:

$ /usr/libexec/java_home
/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home

The user can add to its ~/.profile file (or equivalent) the line:

export JAVA_HOME=`/usr/libexec/java_home`

SWI-Prolog build script picks the value of the JAVA_HOME environment variable but there's a problem. The generated libjpl.dylib looks into the wrong place as you can check by typing:

$ otool -L libjpl.dylib
libjpl.dylib:
    /System/Library/Frameworks/JavaVM.framework/Versions/A/JavaVM (compatibility version 1.0.0, current version 1.0.0)
    ...

This can be corrected by typing:

$ install_name_tool -change /System/Library/Frameworks/JavaVM.framework/Versions/A/JavaVM /Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/server/libjvm.dylib libjpl.dylib

Still, if you try a JPL call (e.g. jpl:jpl_call/4), your SWI-Prolog process will end with an error that "No Java runtime present, requesting install." and a system prompt to install Java 6! If you sigh, throw your hands in the air, surrender, and install Java 6 then JPL will happily work using Java 8. I suspect some lingering linking issue that the fix above is not enough to correct. Is possible that the problem is in the following line in the JPL Makefile:

JAVALIBS=-Wl,-framework,JavaVM

But I have no idea how to fix and still generate a .dylib. Any hints?

Activity

  1. JanWielemaker commented on Dec 7, 2015

    @JanWielemaker
    Member

    As it seems the jpl build is now broken on my machine and it merely includes the old version, this seems a good time to look into this. The first question is which version of Java one is supposed to install how on MacOS? Somehow, my El Captain as a "Java for OS X 2015-001" disk on the desktop. Trying to install it results in some warnings that this is a legacy old version and one should download Java from java.com. Is that what I should be doing for building JPL? Is that what people who actually use Java on MacOS do?

    If I get it build, I might be able to add code to jpl.pl that automates the step above to fix the link target for libjpl.dylib.

  2. anionic commented on Dec 7, 2015

    @anionic
    Contributor

    On 07/12/2015 16:30, Jan Wielemaker wrote:

    As it seems the jpl build is now broken on my machine and it merely
    includes the old version, this seems a good time to look into this.
    The first question is which version of Java one is supposed to install
    how on MacOS? Somehow, my El Captain as a "Java for OS X 2015-001"
    disk on the desktop. Trying to install it results in some warnings
    that this is a legacy old version and one should download Java from
    java.com. Is that what I should be doing for building JPL?

    Of "Java for OS X 2015-001", Apple say:

    This package is exclusively intended for support of legacy software
    and installs the same deprecated version of Java 6 included in the
    014-001 and 2013-005 releases.

    If you need Java, download the latest version of Java for OS X
    directly from Oracle https://www.java.com

    Oracle's is kinda the reference implementation.

    For now, JPL should work fine with Java 6.

    Is that what people who actually use Java on MacOS do?

    Yes if they take Apple's advice ;-) but I guess some will install the
    "deprecated version of Java 6" because they (think they) need it, or
    because it's easier, then not install any newer version.

    If I get it build, I might be able to add code to jpl.pl that
    automates the step above to fix the link target for libjpl.dylib.

    Are you aiming to (be able to) build a binary SWI Prolog for Mac OS X
    x64 which happily links to either legacy Java 6 or recent Oracle/Sun
    Java 8?

    I have received an early Xmas prezzie of a 7 yr old MacBook Pro on
    which I have a fresh El Capitan OS X - can I help?

    Paul Singleton

  3. JanWielemaker commented on Sep 29, 2017

    @JanWielemaker
    Member

    I pushed some stuff that may hopefully resolve this. Building on the Mac now finds and uses the Oracle Java. There is a library for the Mac jpl_config.pl that provides jpl_config_dylib/0 that updates libjpl.dylib. The check_installation/0 linked help page is updated and if JPL fails to load it points at jpl_config_dylib/0 if you are using a Mac.

    I hope that is enough ...

  4. pmoura commented on Sep 29, 2017

    @pmoura
    Author

    After git pull, deleting my installed version, and rebuilding, I get:

    % Loading library(jpl) ......................... FAILED
    Warning: Cannot load required shared library
    Warning: See http://www.swi-prolog.org/build/issues/jpl.html
    

    Calling the jpl_config_dylib/0 indeed fixes the problem for all subsequent runs.

  5. JanWielemaker commented on Sep 29, 2017

    @JanWielemaker
    Member

    Thanks for testing. Should we consider this `good enough' or is there an easy way to make this better? Note that we might not be able to write to libjpl.dylib, there may be no Java at all, etc. If you think this is good enough, please close.

  6. pmoura commented on Sep 30, 2017

    @pmoura
    Author

    Any reason to not automate calling the jpl_config_dylib/0 predicate when building on macOS?

  7. dmpotter44 commented on Nov 14, 2017

    @dmpotter44
    Contributor

    I'm still encountering this with Java 9. However, it looks like it may in fact be a regression in the JDK itself, as apparently earlier Java 8 JDKs would trigger the "No Java runtime present" dialog when started via JNI (JDK-7131356).

  8. JanWielemaker commented on Nov 14, 2017

    @JanWielemaker
    Member

    That seems unrelated. This topic was about finding the Java .dylibs. As the path to find them must be compiled into libjpl.dylib binary distributions need to go through a process of finding the right JDK and updating libjpl.dylib.

  9. dmpotter44 commented on Nov 14, 2017

    @dmpotter44
    Contributor

    There's still an issue with jpl_config_dylib/0 not checking the Java 9 libjvm.dylib location, but I don't know enough Prolog to make it check both locations. (Instead I manually edited the file to only check the Java 9 location.) However it still fails with the "No Java runtime present, requesting install." terminal message. By using DYLD_PRINT_LIBRARIES I can verify it is loading the right JVM, and then blowing up anyway.

  10. JanWielemaker commented on Nov 14, 2017

    @JanWielemaker
    Member

    As I understand it, Java9 dropped jre from the path? I can fix that in jpl_config_dylib/0. Otherwise, I don't know.

  11. dmpotter44 commented on Nov 14, 2017

    @dmpotter44
    Contributor

    Correct. As far as I can tell JPL works under Java 9, but so far I've only been able to use it from the Java side - trying to use JPL within SWI-Prolog directly causes the "No Java runtime present" message.

  12. JanWielemaker commented on Nov 15, 2017

    @JanWielemaker
    Member

    Update jpl_config_dylib/0. That, as I understand, won't fix the problem. I have no clue about that though.

  13. dmpotter44 commented on Nov 15, 2017

    @dmpotter44
    Contributor

    I'm fairly certain at this point that the problem is within the JDK itself. I just realized that the majority of the examples use Swing, and when I run examples/prolog/jpl_versions_demo.pl, everything runs just fine. So as of now, JPL works under Java 9, as long as you don't try and run something that uses Swing. (And possibly other parts of the JDK.) This is definitely not a JPL issue, but it's something people should probably be aware of.

  14. JanWielemaker commented on Nov 16, 2017

    @JanWielemaker
    Member

    Might be an Apple Java issue. There have been problems with swing this in the past too. Shall we close this?

  15. dmpotter44 commented on Dec 1, 2017

    @dmpotter44
    Contributor

    As long as you don't touch AWT, this appears to work. The latest version also solves the problem I had where Homebrew wasn't building JPL with the --with-jpl flag: it was attempting it, but it would fail, and then the SWI-Prolog build would just skip JPL.

    As far as I can tell, everything now "works" with JPL and Java 9 under macOS, minus an internal macOS JDK bug that can be triggered if you call any code that uses AWT (which includes Swing):

    $ java --version
    java 9.0.1
    Java(TM) SE Runtime Environment (build 9.0.1+11)
    Java HotSpot(TM) 64-Bit Server VM (build 9.0.1+11, mixed mode)
    $ swipl --version
    SWI-Prolog version 7.6.3 for x86_64-darwin16.7.0
    $ swipl
    Welcome to SWI-Prolog (threaded, 64 bits, version 7.6.3)
    SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
    Please run ?- license. for legal details.
    
    For online help and background, visit http://www.swi-prolog.org
    For built-in help, use ?- help(Topic). or ?- apropos(Word).
    
    ?- use_module(library(jpl)).
    true.
    
    ?- jpl_new('java.awt.Frame', ['Hello AWT'], F).
    No Java runtime present, requesting install.
    $
    

    However, if you avoid AWT, it works fine:

    ?- use_module(library(jpl)).
    true.
    
    ?- jpl_new('java.io.File', ['demo.pl'], F),
    jpl_call(F, toPath, [], P),
    jpl_call('java.nio.charset.Charset', forName, ['UTF-8'], Utf),
    jpl_call('java.nio.file.Files', readAllLines, [P,Utf], Ls),
    jpl_call(Ls, get, [ 0 ], L).
    F = <jref>(0x7f915869c810),
    P = <jref>(0x7f915869c818),
    Utf = <jref>(0x7f91584c3358),
    Ls = <jref>(0x7f915869c820),
    L = ':- asserta(file_search_path(foreign, \'.\')).'.
    
  16. ssardina commented on Oct 12, 2018

    @ssardina
    Contributor

    Is this true Jan? My students taking the course now (Sept 2018) said that:

    "As the homebrew version does not come with the JPL library (an issue on the homebrew github as been opened about this), the second step is therefore to buid the library from source. Alternatively, you can download the already compiled libjpl.dylib and copy it in:"

    I am asking because your post is from Dec 2017

    I do not have a Mac but they (students) devised this plan to make it work:

    https://github.com/ssardina-research/packages-jpl/wiki/JPL-under-Mac-OS

  17. pmoura commented on Oct 12, 2018

    @pmoura
    Author

    MacPorts is an alternative to Homebrew for installation on macOS. Did you tried it to check if it also have an issue with JPL? I'm the maintainer of the portfile. But, as I use the git version, there have been quite some time since I last used the MacPorts install.

  18. JanWielemaker commented on Oct 13, 2018

    @JanWielemaker
    Member

    Is this true Jan? My students taking the course now (Sept 2018) said that:

    It is true that you can just graph a libjpl.dylib, jpl.pl and jpl.jar from some version and dump it into another with quite a wide variety of versions as both the C API of Prolog and Java are pretty stable. As your student describes, notably on the Mac you have to do some fiddling with the link paths though. On Windows, just make sure the dll and exe are all in the same dir. On Linux it will typically also wok out of the box.

  19. added 3 commits that reference this issue on Nov 19, 2018
    86cf960
    d1281ed
    fba077f
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions