Giter Club home page Giter Club logo

jffi's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jffi's Issues

Duplicate jars published to maven central

I been looking into your project lately and I have found that it has two jars published to maven central. Three if we'd count natives. My very brief look on jffi-1.2.23.jar and jffi-1.2.23-complete.jar shows that they're almost identical. Is there a reason why these are distinct?

I' have noticed that one with complete classifier has a valid OSGI manifest (which I been looking for). If its only one difference then I'd propose to merge both and ship OSGi manifest by default with Main-Class attribute for regular use.

jffi doesn't support for Android at all.

java.lang.UnsatisfiedLinkError: dlopen failed: library "libc.so.6" not found

On android, there is no libc.so.6 at all.
We should compiling for android independently.

IP/License issue found during Eclipse Legal review

JFFI 1.2.7

1.  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
We used part of Netscape's Java Runtime Interface (JRI) as the starting  * point of our design and implementation.
******************************************************************************
* Java Runtime Interface
* Copyright (c) 1996 Netscape Communications Corporation. All rights reserved.

   Code/jffi-1.2.7/jni/win32/include/jni.h


2.  Copyright 2004 Sun Microsystems, Inc. All rights reserved.
 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.

Code/jffi-1.2.7/jni/win32/include/jawt.h
Code/jffi-1.2.7/jni/win32/include/jdwpTransport.h
Code/jffi-1.2.7/jni/win32/include/jni.h
Code/jffi-1.2.7/jni/win32/include/jvmdi.h
Code/jffi-1.2.7/jni/win32/include/jvmpi.h
Code/jffi-1.2.7/jni/win32/include/win32/jawt_md.h
Code/jffi-1.2.7/jni/win32/include/win32/jni_md.h

Code/jffi-1.2.7/jni/win32/include/jvmti.h

Getting an error /tmp/jffi6958730225063734044.so: failed to map segment from shared object

I am using docker-maven-plugin which internally uses jnr/jffi (version 1.12.1) to open ubuntu socket and the plugin is failing with the error Getting an error /tmp/jffi6958730225063734044.so: failed to map segment from shared object
You can find attached the stack trace below (attaching it since it is around 380 lines)

Debugged it a little and found out that the issue is with the loadFromJar API in StubLoader.java

Copying the lib file from jar to /tmp location using nio somehow corrupts the library and triggering the error when loading the copied library using System.load. I verified that by writing a simple Java Program

import java.io.*;
import java.nio.channels.*;
public class Main {
   public static void main(String a[]) throws Exception {
        InputStream is = new FileInputStream(a[0]);
        FileOutputStream os = null;
        File dstFile = File.createTempFile("jffi", "." + dlExtension());
        dstFile.deleteOnExit();
        os = new FileOutputStream(dstFile);
        ReadableByteChannel srcChannel = Channels.newChannel(is);

        for (long pos = 0; is.available() > 0; ) {
            pos += os.getChannel().transferFrom(srcChannel, pos, Math.max(4096, is.available()));
         }

         os.close();
         os = null;
         System.load(dstFile.getAbsolutePath());
 }
}

When using this code with the library built for x86_64-Linux it gives me the same error. i.e. after running the following commands

javac Main.java
mvn clean install -Plinux-profile
java Main target/jni/x86_64-Linux/libjffi-1.2.so 

triggers the same error.

while if I change the code to directly load the library (without any copying) it doesn't trigger an error.

System Details
OS: Ubuntu 16.04
Arch: x86_64.
java version: 1.8.0_121 openjdk

The problem is that I am unable to reproduce that on a physical system with the same configuration. I am consistently able to reproduce that on the VMs that I have.

stack.txt

Support Go c-shared library format

I wanted to try if it's possible to integrate Go code into Java and I tried the easy sample I found. After I wanted to try the arrays too I found this incompatibility. Go use the special GoSlice type for array so the Java String[] can not be mapped to GoSlice. I assume it would require special TypeMapper and replace the default one with the GoSlice specific. Unfortunately I don't know how to do that so I share the information I gathered to help to improve the project.

This is a simple Go code which could be compiled go build -buildmode=c-shared -o libjnr.dylib main.go and it creates the OSX library name. For other OS the output file name should be changed.

// package name: jnr
package main

import "C"
import (
	"encoding/base64"
	"log"
)

//export Multiply
func Multiply(x int64, y int64) int64 {
	return x * y
}

//export Base64Encode
func Base64Encode(in []byte) ([]string) {
	result := make([]string, 2)
	if len(in) < 1 {
		result[1] = "Error"
	}
	result[0] = base64.StdEncoding.EncodeToString(in)
	return result
}

func main() {
	println("go build -buildmode=c-shared -o libjnr.dylib main.go")

	for i, v := range Base64Encode(make([]byte, 0)) {
		log.Printf("array value at [%d]=%v", i, v)
	}

	for i, v := range Base64Encode([]byte("TEST")) {
		log.Printf("array value at [%d]=%v", i, v)
	}
}

The Go generated this .h file, it may help to visualise the GoSlice type.

/* Created by "go tool cgo" - DO NOT EDIT. */

/* package command-line-arguments */

/* Start of preamble from import "C" comments.  */




/* End of preamble from import "C" comments.  */


/* Start of boilerplate cgo prologue.  */

#ifndef GO_CGO_PROLOGUE_H
#define GO_CGO_PROLOGUE_H

typedef signed char GoInt8;
typedef unsigned char GoUint8;
typedef short GoInt16;
typedef unsigned short GoUint16;
typedef int GoInt32;
typedef unsigned int GoUint32;
typedef long long GoInt64;
typedef unsigned long long GoUint64;
typedef GoInt64 GoInt;
typedef GoUint64 GoUint;
typedef __SIZE_TYPE__ GoUintptr;
typedef float GoFloat32;
typedef double GoFloat64;
typedef float _Complex GoComplex64;
typedef double _Complex GoComplex128;

/*
  static assertion to make sure the file is being used on architecture
  at least with matching size of GoInt.
*/
typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1];

typedef struct { const char *p; GoInt n; } GoString;
typedef void *GoMap;
typedef void *GoChan;
typedef struct { void *t; void *v; } GoInterface;
typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;

#endif

/* End of boilerplate cgo prologue.  */

#ifdef __cplusplus
extern "C" {
#endif


extern GoInt64 Multiply(GoInt64 p0, GoInt64 p1);

extern GoSlice Base64Encode(GoSlice p0);

#ifdef __cplusplus
}
#endif

I just wrote a simple Java Example that just loads the Go shared library from the same location where go creates it under $GOPATH

package org.example;


import java.nio.charset.StandardCharsets;

public class App {
    public static interface LibGo {
        long Multiply(long x, long y);

        String[] Base64Encode(byte[] key);
    }

    public static void main(String[] args) throws Exception {
        System.setProperty("jnr.ffi.library.path", "/ FIX-ME $GOPATH/src/example.org/jnr");
        LibGo libc = jnr.ffi.LibraryLoader.create(LibGo.class).load("jnr");

        System.out.println(libc.Multiply(2L, 4L));

        byte[] key = "TEST".getBytes(StandardCharsets.UTF_8);
        String[] res = libc.Base64Encode(key);
        for (int i = 0; i < res.length; i++) {
            System.out.println("array value at [" + i + "]=" + res[i]);
        }
    }
}

When I execute the Java I got this exception.

Exception in thread "main" java.lang.RuntimeException: java.lang.VerifyError: Bad type on operand stack
Exception Details:
  Location:
    org/example/App$LibGo$jnr$ffi$0.Base64Encode([B)[Ljava/lang/String; @32: areturn
  Reason:
    Type long_2nd (current frame, stack[1]) is not assignable to reference type
  Current Frame:
    bci: @32
    flags: { }
    locals: { 'org/example/App$LibGo$jnr$ffi$0', '[B', integer }
    stack: { long, long_2nd }
  Bytecode:
    0x0000000: b200 0e2a b400 122a b400 162b 033d c600
    0x0000010: 0a09 8402 01a7 0004 091c 9a00 07b6 001c
    0x0000020: b01c 2bb8 0022 4e2b 2d2a b400 26b6 002a
    0x0000030: a7ff f0                                
  Stackmap Table:
    full_frame(@24,{Object[#2],Object[#44],Integer},{Object[#24],Object[#46],Long})
    full_frame(@25,{Object[#2],Object[#44],Integer},{Object[#24],Object[#46],Long,Long})
    same_locals_1_stack_item_frame(@32,Long)
    full_frame(@33,{Object[#2],Object[#44],Integer},{Object[#24],Object[#46],Long,Long})

	at jnr.ffi.provider.jffi.AsmLibraryLoader.generateInterfaceImpl(AsmLibraryLoader.java:247)
	at jnr.ffi.provider.jffi.AsmLibraryLoader.loadLibrary(AsmLibraryLoader.java:89)
	at jnr.ffi.provider.jffi.NativeLibraryLoader.loadLibrary(NativeLibraryLoader.java:44)
	at jnr.ffi.LibraryLoader.load(LibraryLoader.java:325)
	at jnr.ffi.LibraryLoader.load(LibraryLoader.java:304)
	at org.example.App.main(App.java:18)
Caused by: java.lang.VerifyError: Bad type on operand stack
Exception Details:
  Location:
    org/example/App$LibGo$jnr$ffi$0.Base64Encode([B)[Ljava/lang/String; @32: areturn
  Reason:
    Type long_2nd (current frame, stack[1]) is not assignable to reference type
  Current Frame:
    bci: @32
    flags: { }
    locals: { 'org/example/App$LibGo$jnr$ffi$0', '[B', integer }
    stack: { long, long_2nd }
  Bytecode:
    0x0000000: b200 0e2a b400 122a b400 162b 033d c600
    0x0000010: 0a09 8402 01a7 0004 091c 9a00 07b6 001c
    0x0000020: b01c 2bb8 0022 4e2b 2d2a b400 26b6 002a
    0x0000030: a7ff f0                                
  Stackmap Table:
    full_frame(@24,{Object[#2],Object[#44],Integer},{Object[#24],Object[#46],Long})
    full_frame(@25,{Object[#2],Object[#44],Integer},{Object[#24],Object[#46],Long,Long})
    same_locals_1_stack_item_frame(@32,Long)
    full_frame(@33,{Object[#2],Object[#44],Integer},{Object[#24],Object[#46],Long,Long})

	at java.lang.Class.getDeclaredConstructors0(Native Method)
	at java.lang.Class.privateGetDeclaredConstructors(Class.java:2671)
	at java.lang.Class.getConstructor0(Class.java:3075)
	at java.lang.Class.getDeclaredConstructor(Class.java:2178)
	at jnr.ffi.provider.jffi.AsmLibraryLoader.generateInterfaceImpl(AsmLibraryLoader.java:236)
	... 5 more

compile on aarch64,and get error like below:

[exec] /data/jffi-1.0.11/jni/libffi/src/arm/sysv.S: Assembler messages:
[exec] /data/jffi-1.0.11/jni/libffi/src/arm/sysv.S:53: error: junk at end of line, first unrecognized character is @' [exec] /data/jffi-1.0.11/jni/libffi/src/arm/sysv.S:144: error: junk at end of line, first unrecognized character is @'
[exec] /data/jffi-1.0.11/jni/libffi/src/arm/sysv.S:145: error: junk at end of line, first unrecognized character is @' [exec] /data/jffi-1.0.11/jni/libffi/src/arm/sysv.S:146: error: junk at end of line, first unrecognized character is @'
[exec] /data/jffi-1.0.11/jni/libffi/src/arm/sysv.S:147: error: junk at end of line, first unrecognized character is @' [exec] /data/jffi-1.0.11/jni/libffi/src/arm/sysv.S:148: error: junk at end of line, first unrecognized character is @'
[exec] /data/jffi-1.0.11/jni/libffi/src/arm/sysv.S:149: error: junk at end of line, first unrecognized character is @' [exec] /data/jffi-1.0.11/jni/libffi/src/arm/sysv.S:151: error: junk at end of line, first unrecognized character is @'
[exec] /data/jffi-1.0.11/jni/libffi/src/arm/sysv.S:152: error: unknown pseudo-op: `.arm'

waht's the matter with this?

Foreign.getInstance().longDoubleFromString returns garbage

The failing of NumberTest.returnDefaultF128HighPrecision is buried here.
To reveal the reason, add the following test case to ForeignTest:
@Test public void longDoubleFromString() { String strValue = "1.234567890123456789"; BigDecimal value = new BigDecimal(strValue); assertEquals(value.toEngineeringString(), value.toString()); byte[] ld = new byte[Type.LONGDOUBLE.size()]; Foreign.getInstance().longDoubleFromString(value.toEngineeringString(), ld, 0, Type.LONGDOUBLE.size()); String strRetValue = Foreign.getInstance().longDoubleToString(ld, 0, 0); // String strRetValueE = Foreign.getInstance().longDoubleToEngineeringString(ld, 0, 0); BigDecimal retValue = new BigDecimal(strRetValue); BigDecimal delta = value.subtract(retValue).abs(); assertTrue("Not equals, expected: " + value.toEngineeringString() + " but was: " + retValue.toEngineeringString(), delta.compareTo(new BigDecimal("0.0000000000000000001")) < 0); }

I will poke in the c sources to figure out whats wrong...

Support IBM Power architecture on Linux.

The new IBM Power architecture on Linux does not appear to be supported by jnr/jffi. The kernel architecture is ppc64le (little endian).

Looking at Java files:
com/kenai/jffi/internal/StubLoader.java
https://github.com/jnr/jffi/blob/master/src/main/java/com/kenai/jffi/internal/StubLoader.java#L159
com/kenai/jffi/Platform.java
https://github.com/jnr/jffi/blob/master/src/main/java/com/kenai/jffi/Platform.java#L196
I do not believe they would match the architecture on ppc64le for the determineCPU() method.

For reference here is the kernel architecture output.

$ uname -a
Linux stilson-01 3.13.0-29-generic #53-Ubuntu SMP Wed Jun 4 21:02:53 UTC 2014 ppc64le ppc64le ppc64le GNU/Linux
$ java -version
java version "1.7.0_55"
OpenJDK Runtime Environment (IcedTea 2.4.7) (7u55-2.4.7-1ubuntu1)
OpenJDK 64-Bit Zero VM (build 24.51-b03, interpreted mode)

Classes like this use Java system properties to determine architecture. Here is a listing of the environment properties from OpenJDK running on the same Power system:

$ java Jvm
-- listing properties --
java.runtime.name=OpenJDK Runtime Environment
sun.boot.library.path=/usr/lib/jvm/java-7-openjdk-ppc64el/j...
java.vm.version=24.51-b03
java.vm.vendor=Oracle Corporation
java.vendor.url=http://java.oracle.com/
path.separator=:
java.vm.name=OpenJDK 64-Bit Zero VM
file.encoding.pkg=sun.io
user.country=US
sun.java.launcher=SUN_STANDARD
sun.os.patch.level=unknown
java.vm.specification.name=Java Virtual Machine Specification
user.dir=/home/ubuntu/mbruzek/java
java.runtime.version=1.7.0_55-b14
java.awt.graphicsenv=sun.awt.X11GraphicsEnvironment
java.endorsed.dirs=/usr/lib/jvm/java-7-openjdk-ppc64el/j...
**os.arch**=ppc64le
java.io.tmpdir=/tmp
line.separator=

java.vm.specification.vendor=Oracle Corporation
**os.name**=Linux
sun.jnu.encoding=UTF-8
**java.library.path**=/usr/java/packages/lib/ppc64le:/usr/lib/powerpc64le-linux-gnu/jni:/lib/powerpc64le-linux-gnu:/usr/lib/powerpc64le-linux-gnu:/usr/lib/jni:/lib:/usr/lib
java.specification.name=Java Platform API Specification
java.class.version=51.0
os.version=3.13.0-29-generic
user.home=/home/ubuntu
user.timezone=
java.awt.printerjob=sun.print.PSPrinterJob
file.encoding=UTF-8
java.specification.version=1.7
user.name=ubuntu
java.class.path=.
java.vm.specification.version=1.7
**sun.arch.data.model**=64
java.home=/usr/lib/jvm/java-7-openjdk-ppc64el/jre
sun.java.command=Jvm
java.specification.vendor=Oracle Corporation
user.language=en
awt.toolkit=sun.awt.X11.XToolkit
java.vm.info=interpreted mode
java.version=1.7.0_55
java.ext.dirs=/usr/lib/jvm/java-7-openjdk-ppc64el/j...
sun.boot.class.path=/usr/lib/jvm/java-7-openjdk-ppc64el/j...
java.vendor=Oracle Corporation
file.separator=/
java.vendor.url.bug=http://bugreport.sun.com/bugreport/
sun.cpu.endian=little
sun.io.unicode.encoding=UnicodeLittle
sun.cpu.isalist=

Making jffi-s390x-Linux.jar available

Hi All,

JRuby is lacking support of s390x architecture to load jffi library. When raised the following issue
jruby/jruby#4632, I came to know I can build jffi on 390x platform and upload the jar file by creating a PR. My question is, I can build the master branch and make the jar file available but how will be latest released version taken care off by the community? Do in need to upload the jar file for every release or else by providing hardware community will take care of this thing? Is there any CI is in place for this?
CC
@headius

Close library

Is there a way to close a previously opened library?
I would like to delete the dll file associated to a given loaded library when I don't need it anymore.

Could not load the native lib from jffi-native when launching in Android system

I use jnr-ffi to bind native code to java code but I ran into a problem that cannot detect the CPU size from Platform#calculateAddressSize() because the line of code alway throw error
int dataModel = Integer.getInteger("sun.arch.data.model");
So I fix the problem by clone your code and using another system property (os.arch) and rebuild the jar file. After that, I detect another problem in jffi lib that not support arm CPU architecture. The incorrect method is here that it's missing some architecture like i486,i586,i686,i786 (typically is android emulator x86) and arm architecture. So I need to modify code and rebuild the jar file of jffi lib.
Everything is OK when I run new code in java app but isn't in Android app. The full stack trace is following

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.jollyjoker992.bitmarksamplektl, PID: 21303
java.lang.UnsatisfiedLinkError: could not load FFI provider jnr.ffi.provider.jffi.Provider
at jnr.ffi.provider.InvalidProvider$1.loadLibrary(InvalidProvider.java:48)
at jnr.ffi.LibraryLoader.load(LibraryLoader.java:325)
at jnr.ffi.LibraryLoader.load(LibraryLoader.java:304)
at cryptography.crypto.libsodium.LibSodium.sodium(LibSodium.java:29)
at cryptography.crypto.SecretBox.generateSecretBox(SecretBox.java:27)
at sdk.features.Account.generateKeyPair(Account.java:105)
at sdk.features.Account.fromSeed(Account.java:47)
at com.example.jollyjoker992.bitmarksamplektl.MainActivity.onCreate(MainActivity.kt:24)
at android.app.Activity.performCreate(Activity.java:6251)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: java.lang.UnsatisfiedLinkError: could not get native definition for type: POINTER
at com.kenai.jffi.Type$Builtin.lookupTypeInfo(Type.java:251)
at com.kenai.jffi.Type$Builtin.getTypeInfo(Type.java:237)
at com.kenai.jffi.Type.resolveSize(Type.java:155)
at com.kenai.jffi.Type.size(Type.java:138)
at jnr.ffi.provider.jffi.NativeRuntime$TypeDelegate.size(NativeRuntime.java:178)
at jnr.ffi.provider.AbstractRuntime.(AbstractRuntime.java:48)
at jnr.ffi.provider.jffi.NativeRuntime.(NativeRuntime.java:57)
at jnr.ffi.provider.jffi.NativeRuntime.(NativeRuntime.java:41)
at jnr.ffi.provider.jffi.NativeRuntime$SingletonHolder.(NativeRuntime.java:53)
at jnr.ffi.provider.jffi.NativeRuntime.getInstance(NativeRuntime.java:49)
at jnr.ffi.provider.jffi.Provider.(Provider.java:29)
at java.lang.Class.newInstance(Native Method)
at jnr.ffi.provider.FFIProvider$SystemProviderSingletonHolder.getInstance(FFIProvider.java:68)
at jnr.ffi.provider.FFIProvider$SystemProviderSingletonHolder.(FFIProvider.java:57)
at jnr.ffi.provider.FFIProvider.getSystemProvider(FFIProvider.java:35)
at jnr.ffi.LibraryLoader.create(LibraryLoader.java:73)
at cryptography.crypto.libsodium.LibSodium.sodium(LibSodium.java:29) 
Disconnected from the target VM, address: 'localhost:8601', transport: 'socket'
at cryptography.crypto.SecretBox.generateSecretBox(SecretBox.java:27) 
at sdk.features.Account.generateKeyPair(Account.java:105) 
at sdk.features.Account.fromSeed(Account.java:47) 
at com.example.jollyjoker992.bitmarksamplektl.MainActivity.onCreate(MainActivity.kt:24) 
at android.app.Activity.performCreate(Activity.java:6251) 
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107) 
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369) 
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 
at android.app.ActivityThread.-wrap11(ActivityThread.java) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) 
at android.os.Handler.dispatchMessage(Handler.java:102) 
at android.os.Looper.loop(Looper.java:148) 
at android.app.ActivityThread.main(ActivityThread.java:5417) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
Caused by: java.lang.UnsatisfiedLinkError: java.lang.UnsatisfiedLinkError: could not locate stub library in jar file. Tried [jni/arm-Linux/libjffi-1.2.so, /jni/arm-Linux/libjffi-1.2.so]
at com.kenai.jffi.internal.StubLoader.getStubLibraryStream(StubLoader.java:418)
at com.kenai.jffi.internal.StubLoader.loadFromJar(StubLoader.java:361)
at com.kenai.jffi.internal.StubLoader.load(StubLoader.java:264)
at com.kenai.jffi.internal.StubLoader.(StubLoader.java:455)
at java.lang.Class.classForName(Native Method)
at java.lang.Class.forName(Class.java:324)
at com.kenai.jffi.Init.load(Init.java:68)
at com.kenai.jffi.Foreign$InstanceHolder.getInstanceHolder(Foreign.java:49)
at com.kenai.jffi.Foreign$InstanceHolder.(Foreign.java:45)
at com.kenai.jffi.Foreign.getInstance(Foreign.java:103)
at com.kenai.jffi.Type$Builtin.lookupTypeInfo(Type.java:242)
at com.kenai.jffi.Type$Builtin.getTypeInfo(Type.java:237)
at com.kenai.jffi.Type.resolveSize(Type.java:155)
at com.kenai.jffi.Type.size(Type.java:138)
at jnr.ffi.provider.jffi.NativeRuntime$TypeDelegate.size(NativeRuntime.java:178)
at jnr.ffi.provider.AbstractRuntime.(AbstractRuntime.java:48)
at jnr.ffi.provider.jffi.NativeRuntime.(NativeRuntime.java:57)
at jnr.ffi.provider.jffi.NativeRuntime.(NativeRuntime.java:41)
at jnr.ffi.provider.jffi.NativeRuntime$Single

mips64el-linux binary disables stack guard

Apparently the mips64el-linux binary we have disables the "stack guard", causing Hotspot to complain thusly:

OpenJDK 64-Bit Server VM warning: You have loaded library /tmp/jffi4965776428901618408.so which might have disabled stack guard. The VM will try to fix the stack guard now.
SUREFIRE-859: It's highly recommended that you fix the library with 'execstack -c <libfile>', or link it with '-z noexecstack'.

Needs to be fixed, but perhaps this warning indicates that the JVM is working around it?

No-ascii Windows username cause UnsatisfiedLinkError exception

at com.kenai.jffi.Foreign.newLoadError(Foreign.java:72)
at com.kenai.jffi.Foreign.access$300(Foreign.java:42)
at com.kenai.jffi.Foreign$InValidInstanceHolder.getForeign(Foreign.java:98)
at com.kenai.jffi.Foreign.getInstance(Foreign.java:103)
at com.kenai.jffi.Library.openLibrary(Library.java:157)
at com.kenai.jffi.Library.getCachedInstance(Library.java:131)
at org.python.modules.jffi.DynamicLibrary.(DynamicLibrary.java:26)
at org.python.modules.jffi.jffi.dlopen(jffi.java:43)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
java.lang.UnsatisfiedLinkError: java.lang.UnsatisfiedLinkError: java.lang.UnsatisfiedLinkError: C:\Users\Sa?ol\AppData\Local\Temp\jffi946630297317024306.dll: Can't find dependent libraries
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1941)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1824)
at java.lang.Runtime.load0(Runtime.java:809)
at java.lang.System.load(System.java:1086)
at com.kenai.jffi.internal.StubLoader.loadFromJar(StubLoader.java:371)
at com.kenai.jffi.internal.StubLoader.load(StubLoader.java:258)
at com.kenai.jffi.internal.StubLoader.(StubLoader.java:444)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:348)
at com.kenai.jffi.Init.load(Init.java:68)
at com.kenai.jffi.Foreign$InstanceHolder.getInstanceHolder(Foreign.java:49)
at com.kenai.jffi.Foreign$InstanceHolder.(Foreign.java:45)
at com.kenai.jffi.Foreign.getInstance(Foreign.java:103)
at com.kenai.jffi.Type$Builtin.lookupTypeInfo(Type.java:242)
at com.kenai.jffi.Type$Builtin.getTypeInfo(Type.java:237)
at com.kenai.jffi.Type.resolveSize(Type.java:155)

I'm using jython-standalone-2.7.1.patch2609.jar depending com.kenai.jffi.internal.StubLoader does, the root cause is the defact of System.load() function can not handle no-ascii path param. see:
libgdx/libgdx#5524

Invoker fails to correctly pass arguments to Foreign is some edge cases.

I ran into an issue today using JNR-FFI where we are using a mix of Direct and Heap ByteBuffers and had C interface that looked something like `int method(char *c1, char *c2, long c2len, char *c3, char *c4) and I found that depending on where the direct ByteBuffer was in the mix of heap ByteBuffers, either one pointed was passed to the C interface wrong or JNR-FFI refused since it thought the direct object was a heap object. I tracked the issue into the logic in Invoker that sorts out the correct foreign invocation. This only seems to be an issue where N > 3 where the "switch" algorithm is used.

I've added failing unit tests to InvokerTest in pull request #21 that demonstrate the issue.

Fails loading *.so from docker container on raspberry pi

Hi,
I am using this library (actually jnr-unixsocket) to create a dbus connection in a docker container.

It works outside of a docker container, while fails in it with:
(UPDATE) It seems not to work in the host system and neither in the container

java.lang.UnsatisfiedLinkError: java.lang.UnsatisfiedLinkError: /usr/src/app/tmp/jffi2917909324910245781.so: /usr/src/app/tmp/jffi2917909324910245781.so: cannot open shared object file: No such file or directory

Inspecting the container fs I find the library. I tried changing the java.io.tmpdir but no luck and also set 777 to avoid any permission error.

Relevant sources are here for reference

Do you have any suggestion?

I would be glad to help testing if needed.

Thanks

UPDATE2: Related to #30

support ulong_long

ulong_long type is represented as long which is not enough for corner values

https://github.com/jruby/jruby/blob/b267aa1e495670edcd0c919d92a4228fd3de7944/core/src/main/java/org/jruby/ext/ffi/AbstractMemory.java#L782

https://github.com/ffi/ffi/blob/1091ff7e7efe7bb49231a4a0107dcd2022ed7642/spec/ffi/struct_spec.rb#L367

  1) Struct tests ulong_long field r/w (8000000000000000)
     Failure/Error: s[:v] = obj

     RangeError:
       bignum too big to convert into `long'
     # ./spec/ffi/struct_spec.rb:347:in `test_num_field'
     # ./spec/ffi/struct_spec.rb:358:in `block in int_field_test'

  2) Struct tests ulong_long field r/w (ffffffffffffffff)
     Failure/Error: s[:v] = obj

     RangeError:
       bignum too big to convert into `long'
     # ./spec/ffi/struct_spec.rb:347:in `test_num_field'
     # ./spec/ffi/struct_spec.rb:358:in `block in int_field_test'

refs jruby/jruby#6375

Cross-compiling for CI and release artifacts

We need to set up some builds so we can regenerate the native binaries on the platforms we support. Recent changes for better BSD support have needed tweaks to the jffi native library, and the difficulty of getting new builds has basically killed our ability to evolve this small native part of JNR.

@smortex pointed out in #66 that Cirrus-CI has support for Windows, Linux, MacOS, and FreeBSD, which covers a lot of platforms in one place.

Travis CI obviously supports Linux and MacOS and early preview of Windows.

Azure only supports Windows and Linux, which I expect also applies to Azure DevOps and that whole pipelines thing.

Obviously we can set up VMs on any cloud service, or perhaps use e.g. Amazon AMIs for the x86-based operating systems we want, but this would be the most labor-intensive option.

If there's something virtual or Docker-like, or a comprehensive set of cross-compilation tools we can Docker down to a local system, that would be acceptable too.

cc @tuxillo @Freaky @tduehr

Support for OS400

There currently isn't jffi support for IBM's OS400** operating system and I am attempting to build jffi from a git clone of the current master. I see @pierrickrouxel is also working through this issue in the JRuby project and also this issue. Should I be logging this issue here or in the JRuby issues?

**Now known as IBM i or just i. You might also hear it referred to as iSeries.

What I've Done
I've made some changes to the build process (see fork) to support OS400 but have come to a point where I need input because the build isn't completing. The config.log declares alloca support was found, but alloca does NOT exist on OS400.

from config.log

. . .
| #define HAVE_ALLOCA_H 1
| #define HAVE_ALLOCA 1
. . .

The stdout to my shell gives more information - specifically:

 [exec] /home/aaron/git/jffi/jni/jffi/LongDouble.c:82:5: error: implicit declaration of function 'alloca' [-Werror=implicit-function-declaration]
 [exec] /home/aaron/git/jffi/jni/jffi/LongDouble.c:82:11: error: incompatible implicit declaration of built-in function 'alloca' [-Werror]
 [exec] cc1: all warnings being treated as errors
 [exec]
 [exec] /home/aaron/git/jffi/jni/GNUmakefile:295: recipe for target '/home/aaron/git/jffi/build/jni/jffi/LongDouble.o' failed
 [exec] gmake: *** [/home/aaron/git/jffi/build/jni/jffi/LongDouble.o] Error 1

Fix javadoc errors for release builds on Java 8+

Java 8+ (or at least OpenJDK 8+) now enforces some lint-like rules on javadocs. We currently fail some of these checks, preventing release builds from being performed on OpenJDK 8. We need to fix this.

Compilation failure

Using java -version
openjdk version "11.0.7" 2020-04-14
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.7+10)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.7+10, mixed mode)

Ant compilation failed with error

...
-generate-native-headers:
    [mkdir] Skipping /home/test/jffi-jffi-1.2.23/build/jni because it already exists.
    [mkdir] Skipping /home/test/jffi-jffi-1.2.23/build/classes because it already exists.
    [javah] Compilation arguments:
    [javah] '-d'
    [javah] '/home/test/jffi-jffi-1.2.23/build/jni'
    [javah] '-classpath'
    [javah] '/home/test/jffi-jffi-1.2.23/build/classes'
    [javah] '-force'
    [javah]
    [javah] The ' characters around the executable and arguments are
    [javah] not part of the command.
    [javah] Classes to be compiled:
    [javah]     com.kenai.jffi.Foreign
    [javah]     com.kenai.jffi.ObjectBuffer
    [javah]     com.kenai.jffi.Version

BUILD FAILED
/home/test/jffi-jffi-1.2.23/build.xml:300: Can't load javah
        at org.apache.tools.ant.taskdefs.optional.javah.SunJavah.compile(SunJavah.java:60)
        at org.apache.tools.ant.taskdefs.optional.Javah.execute(Javah.java:472)
        at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:292)
        at jdk.internal.reflect.GeneratedMethodAccessor4.invoke(Unknown Source)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
        at org.apache.tools.ant.Task.perform(Task.java:348)
        at org.apache.tools.ant.Target.execute(Target.java:435)
        at org.apache.tools.ant.Target.performTasks(Target.java:456)
        at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1393)
        at org.apache.tools.ant.Project.executeTarget(Project.java:1364)
        at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
        at org.apache.tools.ant.Project.executeTargets(Project.java:1248)
        at org.apache.tools.ant.Main.runBuild(Main.java:851)
        at org.apache.tools.ant.Main.startAnt(Main.java:235)
        at org.apache.tools.ant.launch.Launcher.run(Launcher.java:280)
        at org.apache.tools.ant.launch.Launcher.main(Launcher.java:109)
Caused by: java.lang.ClassNotFoundException: com.sun.tools.javah.Main
        at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
        at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
        at java.base/java.lang.Class.forName0(Native Method)
        at java.base/java.lang.Class.forName(Class.java:315)
        at org.apache.tools.ant.taskdefs.optional.javah.SunJavah.compile(SunJavah.java:57)
        ... 17 more

Total time: 0 seconds

Security - disable loading of jffi-1.2.dll from current directory

My application is run on Windows and it embeds JRuby.
I've noticed that jffi-1.2.dll file is loaded from current directory first and if not found binary distributed with application is stored in Temp and loaded.
This can lead to security problem - malicious file residing in Downloads folder with my jar file is loaded and executed instead of file distributed inside jar file.
How can I disable this behavior?

LongDouble.c Java_com_kenai_jffi_Foreign_longDoubleFromString Misuse of args

a byte array, the insertOffset and the length of that byte array is passed.
then in jffi_encodeLongDouble the length of the array is confused with the insert length because offset is ignored in that comparison.

Solution:
The ability to insert at offset is not used, so why not create that array in the native code and return that array?

@headius why is that method not static? the object reference is not used?!

Corrected RTLD-accessing logic needs to be in a major release

I just reverted the changes in b6d8a9f (via 9c5a077) by @tduehr, not because they weren't the right thing to do, but because they will require us to rebuild the native library across all platforms. This was preventing us from releasing jffi 1.2.8 and bumping upstream projects to depend on it, which has in turn blocked numerous important jffi fixes from getting into the hands of users.

We'll need to talk about a strategy for making this change and getting all our binaries rebuilt, and any changes to the native bits probably needs to happen in a major release (a 1.3 or 2.0, depending on what our versioning considers major).

cc @enebo

Implement critical JNI endpoints and primitive array pass-through

In jnr/jnr-ffi#68 we learned that there's a way to bind JNI methods with considerably reduced overhead, if you follow some rules detailed here:

http://stackoverflow.com/questions/36298111/is-it-possible-to-use-sun-misc-unsafe-to-call-c-functions-without-jni/36309652#36309652

In order to support the ability to mark bound functions as "critical" and primitive arrays as "pass through" in jnr/jnr-ffi#86, we need to implement some new native bindings in jffi and possibly ways to tell the invokes that the primitive arrays being passed are not to be dealt with in the usual JNI way.

Provide an alternative to load libffi from another directory

@headius I'm not sure if I'm missing something. Today on StubLoader, the only way to load Native libraries is reading it from jni/" + getPlatformName() + "/" + System.mapLibraryName(stubLibraryName).

But that represents a problem for us on Keycloak, because there are several restrictions about having native C inside a jar (this is specific to the project). That's easily achieved with maven shade and is not a problem. But now we would like to load libffi, from an external source. For example: /usr/lib64/libffi.so.

I tried to override system properties with -Djava.library.path=/opt/lib64 -Djffi.boot.library.path=/opt/lib64, without too much success.

I wonder if we could provide an alternative for people with this very specific scenario, to specify the location of libffi. I would be more than happy to provide a PR if that doesn't exist today.

Loading 32bit library when 64bit one is available

A colleague of mine has two versions of libcrypt.so.1 on Kubuntu 15.04.

/lib/i386-linux-gnu/libcrypt.so.1
/lib/x86_64-linux-gnu/libcrypt.so.1

JFFI, on behalf of jnr-posix, is loading the 32bit one when it should load the 64bit one. What is the mechanism, either in the OS or JFFI or wherever, that should ensure the correct one is loaded, and what could be going wrong here?

The 32bit library is needed by Skype for Linux, so it is not an obscure package.

Missing native library dependency for dbus service

I'm using this through signal-cli, I initially opened an issue there (AsamK/signal-cli#321) and the maintainer rightfully redirected me here.

I'm having an error message with one architecture: aarch64 (rpi4)

Missing native library dependency for dbus service: could not load FFI provider jnr.ffi.provider.jffi.Provider

Is this something path related that I can fix myself or a know issue?

Ability to log uncaught exceptions in closures?

Would be nice to be able to either register a callback for uncaught exceptions or toggle on/off calls to ExceptionDescribe when calling into Java functions from C. You call these closures? To clarify I mean uncaught exceptions from the jnr-ffi's "@DeleGate" methods.

allow override of tmp dir to extract jffi native stub

Hi, I would like a new property to be able to override the StubLoader's use of java.io.tmpdir with another directory.

In commit b0992bb there is now a very clear error recommending to have the tmp directory be noexec. However, given the large number of libraries that can potentially use java.io.tmpdir, this raises a security concern. Especially for web servers where there is a desire to lock down the temp directory for uploads/downloads, it would be great to put noexec on it. Executable temporary files are the exception rather than the rule, and so it's best if they can be handled separately.

JFFI does provide some boot path options already, which is helpful, however these do not extract the stub from the jar.

See lmdbjava/lmdbjava#155 for an example of a downstream library using JFFI, which is now able to customize its own shared library location.

Ant test on jffi throws errors

I am working on jffi – 1.2.16 on Ubuntu 16.04. I have built it from source and successfully executed commands ant, ant jar && ant archive-platform-jar && mvn package .

While running ant test command , observed errors.
Please see logs in comments section.

Support for android

Is there any plan to support android? Things like StubLoader doesn't support "armv7" CPU.
Would be good to know about the strategy.

May be helpful to make StubLoader like a application provided class (<application_package>.$StubLoader) using reflection and if application doesn't provide then fall back to "internal.StubLoader".

Happy to hear on this.

Release notes/changelog

Is it possible to provide release notes or changelog so that we know what have been changed in each version?

Can't find libjffi-1.2.so on Raspbian Raspberry Pi

I have been running this library on my Mac OS machine with no problem but am experiencing a world of pain when it comes to running on my Raspberry Pi.

The crux of the problem is that this library fails to load "libjffi-1.2.so". I can see it is searching in various locations where the file does exist. I can also see that it is trying to access some long tmp file with a .so extension from /tmp.

Basically, the errors are basically showing me the path where the failed to be read but for some of them the file exists in the relevant path, which should have been picked up, but it's not.

Some things I have tried to no avail:

  • set java.library.path
  • set LD_LIBRARY_PATH
  • sudo apt get install libjna-java
  • set java.io.tmpdir to a local folder to alleviate any possible perm issues with /tmp
  • sudo ldconfig

Also, please note I am using the appropriate arm-linux version of libjffi-1.2.so.

None of these have worked so I am turning to this repo for assistance. Does anybody know why I am experiencing such pain? Yes it is pain because I have been trying for ages to get this working :(

Any help will be greatly appreciated.

Increase macOS build to at least 10.9 SDK

When trying to notarize our app via Apple's notarization service, we get the following warning for libjffi-1.2.jnilib:

The binary uses an SDK older than the 10.9 SDK.

See official documentation on this warning: https://developer.apple.com/documentation/security/notarizing_your_app_before_distribution/resolving_common_notarization_issues#3087723

That means it's not an issue to keep the deployment target at 10.6 but it would be great if the linked SDK could be increased from 10.7 to 10.9. Would that be possible?

Actually, it wouldn't just be great, it will be necessary soon. If I'm not mistaken, beginning with January 2020, see: https://developer.apple.com/news/?id=09032019a

And also:

Notarisation requires the hardened runtime, the hardened runtime requires library validation, and library validation requires that you link with (at least) the 10.9 SDK.

(https://forums.developer.apple.com/thread/115679#357047)

Use JIT-compiled stubs instead of LibFFI where possible

In some cases, it is possible to avoid using libffi, instead generating a machine-code trampoline that just shuffles the parameters and tail-calls the native function. This should be faster.

This won't work for the case of critical natives, though, unless we are able to make the JVM's dynamic lookup (via dlopen and dlsym) find the JIT-compiled code. This is because critical natives cannot be registered using RegisterNatives.

Build failure with Java 10 due to the removal of javah

Hi, jffi fails to build with Java 10 or later due to the removal of the javah tool. We fixed this in Debian by:

  • removing the <javah> task in the Ant build
  • adding the nativeHeaderDir to the <javac> tasks
  • adding the @Native annotation (introduced in Java 8) to the fields in ObjectBuffer.java and Version.java used by the native code

Here is the patch we used: https://salsa.debian.org/java-team/jffi/blob/master/debian/patches/java10-compatibility.patch

Compiling and running jffi for powerpc64-AIX gives illegal instructions errors

System Details

Running on powerpc64-AIX 7.1, with gcc 4.9.4, build vars as follows:

export OBJECT_MODE=64
export CONFIG_SHELL=/opt/freeware/bin/bash
export CONFIG_ENV_ARGS=/opt/freeware/bin/bash

export CC="gcc -mcpu=power4 -mtune=power4 -maix64 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGE_FILES"

export CFLAGS="-DSYSV -D_AIX -D_AIX32 -D_AIX41 -D_AIX43 -D_AIX51 -D_AIX61 -D_AIX71 -D_ALL_SOURCE -DFUNCPROTO=15 -O -I/opt/freeware/include"
export LD=ld
export LDFLAGS="-L/opt/freeware/lib64 -L/opt/freeware/lib -Wl,-blibpath:/opt/freeware/lib64:/opt/freeware/lib:/usr/lib:/lib -Wl,-bmaxdata:0x80000000"

export PATH=/usr/bin:/bin:/etc:/usr/sbin:/usr/ucb:/usr/bin/X11:/sbin:/usr/vac/bin:/usr/vacpp/bin:/usr/ccs/bin:/usr/dt/bin:/usr/opt/perl5/bin:/opt/freeware/bin:/opt/freeware/sbin:/usr/local/bin:/usr/lib/instl

export JAVA_HOME=/usr/java7_64
export ANT_HOME=/opt/apache-ant

export PATH="${JAVA_HOME}/bin:${ANT_HOME}/bin:$PATH:/opt/freeware/bin"

Problems Description

Compiling and running a test program with jffi throws errors and crashes. Trying an unmodified ant jar gives the following error:

gmake[3]: Leaving directory '/home/tcr/jffi/build/jni/libffi-ppc64-aix'
gmake[2]: Leaving directory '/home/tcr/jffi/build/jni/libffi-ppc64-aix'
gmake[1]: Leaving directory '/home/tcr/jffi/build/jni/libffi-ppc64-aix'
In file included from /home/tcr/jffi/build/jni/libffi-ppc64-aix/include/ffi.h:67:0,
                 from /home/tcr/jffi/jni/jffi/jffi.h:45,
                 from /home/tcr/jffi/jni/jffi/Array.c:39:
/home/tcr/jffi/build/jni/libffi-ppc64-aix/include/ffitarget.h:159:5: error: "_CALL_ELF" is not defined [-Werror=undef]
 #if _CALL_ELF == 2

Modifying the GNUmakefile with the following change allows compilation, though:

diff --git a/jni/GNUmakefile b/jni/GNUmakefile
index 85ab6f2..7942f45 100755
--- a/jni/GNUmakefile
+++ b/jni/GNUmakefile
@@ -66,8 +66,10 @@ OFLAGS = -O2 $(JFLAGS)
 # MacOS headers aren't completely warning free, so turn them off
 WERROR = -Werror
 ifneq ($(OS),darwin)
+ifneq ($(OS),aix)
   WFLAGS += -Wundef $(WERROR)
 endif
+endif
 WFLAGS += -W -Wall -Wno-unused -Wno-parentheses -Wno-unused-parameter
 PICFLAGS = -fPIC
 SOFLAGS = # Filled in for each OS specifically

Compiling and running this C program with the library works (both static and dynamic):

#include <ffi.h>
#include <stdio.h>
#include <dlfcn.h>

int main(int argc, char **argv)
{
    if (argc < 2) {
        fputs("Must specify a library on the command line\n", stderr);
        return 1;
    }
    // Load in the library itself
    void *libhandle = dlopen(argv[1], RTLD_LOCAL | RTLD_LAZY | RTLD_MEMBER);
    if (!libhandle) {
        fputs("Could not link library\n", stderr);
        fprintf(stderr, "%s\n", dlerror());
        return 1;
    }
    void *fun = dlsym(libhandle, "sqlite3_libversion");
    if (!fun) {
        fputs("Could not find symbol in library\n", stderr);
        fprintf(stderr, "%s\n", dlerror());
        return 1;
    }

    // Set up libffi stuff
    ffi_cif cif;
    ffi_type *arg_types[0];

    /* Initialize the cif */
    if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 0, &ffi_type_pointer, arg_types) == FFI_OK)
    {
        ffi_arg retval;
        ffi_call(&cif, fun, &retval, NULL);
        puts((const char *)retval);
    }
    dlclose(libhandle);
    return 0;
}
$ $CC -o ffitest ffitest.c $CFLAGS $LDFLAGS jffi/build/jni/libffi-ppc64-aix/.libs/libffi.a
$ ./ffitest 'libsqlite3.a(libsqlite3.so.0)'
3.8.8.3
$ $CC -o ffitest ffitest.c $CFLAGS $LDFLAGS jffi/build/jni/libffi-ppc64-aix/.libs/libffi.so.6 
$ LD_LIBRARY_PATH=jffi/build/jni/libffi-ppc64-aix/.libs ./ffitest 'libsqlite3.a(libsqlite3.so.0)'
3.8.8.3
tcr@api-lou-jum01-p ~ $ LD_LIBRARY_PATH=jffi/build/jni/libffi-ppc64-aix/.libs ldd ./ffitest  
./ffitest needs:
         /usr/lib/libc.a(shr_64.o)
         jffi/build/jni/libffi-ppc64-aix/.libs/libffi.so.6
         /unix
         /usr/lib/libcrypt.a(shr_64.o)
         /opt/freeware/lib64/libgcc_s.a(shr.o)
         /usr/lib/libpthreads.a(shr_xpg5_64.o)

However, a simple Java example using jffi, when compiled with this in the archive, fails:

package com.absperf.ffitest;

import com.kenai.jffi.Invoker;
import com.kenai.jffi.Type;
import com.kenai.jffi.Library;
import com.kenai.jffi.Function;
import com.kenai.jffi.MemoryIO;
import com.kenai.jffi.HeapInvocationBuffer;
import com.kenai.jffi.ArrayFlags;

public class App 
{
    public static void main(String[] args) {
        Library lib = Library.openLibrary(args[0], Library.LOCAL | Library.NOW);
        if (lib == null) {
            System.err.print("Error!:  ");
            System.err.println(lib.getLastError());
            System.exit(1);
        }
        System.out.println("GetSymbolAddress");
        long func_address = lib.getSymbolAddress("sqlite3_libversion");
        if (func_address == 0) {
            System.err.print("Error; could not find function address:  ");
            System.err.println(lib.getLastError());
            System.exit(1);
        }
        System.out.println("make function");
        Function func = new Function(func_address, Type.POINTER);
        System.out.println("make buffer");
        HeapInvocationBuffer buf = new HeapInvocationBuffer(func);
        MemoryIO mem = MemoryIO.getInstance();
        System.out.println("put pointers");
        Invoker invoker = Invoker.getInstance();
        System.out.println("invoke function");
        long address = invoker.invokeAddress(func, buf);
        System.out.println(new String(mem.getZeroTerminatedByteArray(address)));
    }
}

On Linux:

$ java -jar ./target/ffitest-1.0-SNAPSHOT-shaded.jar libsqlite3.so
GetSymbolAddress
make function
make buffer
put pointers
invoke function
3.23.1

On AIX:

$ /usr/java7_64/bin/java -jar ~/ffitest-1.0-SNAPSHOT-shaded.jar 'libsqlite3.a(libsqlite3.so.0)'
GetSymbolAddress
make function
make buffer
put pointers
invoke function
Unhandled exception
Type=Illegal instruction vmState=0x00040000
J9Generic_Signal_Number=00000010 Signal_Number=00000004 Error_Value=00000000 Signal_Code=0000001e
Handler1=09001000A0277D10 Handler2=09001000A026DAE0
R0=0000000000000000 R1=000001001012F690 R2=0000000000000000 R3=0000010010423D50
R4=0000010010423EF8 R5=000001001012F760 R6=0000010010423EF8 R7=0900000000654094
R8=0000010010423C70 R9=000001001012F760 R10=09001000A027B6D0 R11=0000000000000000
R12=000000008200042B R13=000001001013A800 R14=00000000600257A0 R15=0000000060000100
R16=0000000000000007 R17=0000000000000000 R18=09001000A027C4E8 R19=09001000A07254C0
R20=0000000060107EE0 R21=00000000600257E8 R22=0000000000000000 R23=0000010010474090
R24=09001000A071D4A8 R25=000000000000007E R26=0000000000000000 R27=0000000000000000
R28=000001001012F720 R29=09001000A071D4A8 R30=000001001012F940 R31=0000000000000008
IAR=0000000000000000 LR=09000000024D3C40 MSR=A00000000000D032 CTR=0000000000000000
CR=2000242220000002 FPSCR=8200000000000000 XER=2000000282000000
FPR0 0000000000000000 (f: 0.000000, d: 0.000000e+00)
FPR1 404d800000000000 (f: 0.000000, d: 5.900000e+01)
FPR2 41e0000000000000 (f: 0.000000, d: 2.147484e+09)
FPR3 3fe8000000000000 (f: 0.000000, d: 7.500000e-01)
FPR4 3fa9999a00000000 (f: 0.000000, d: 5.000001e-02)
FPR5 412e848000000000 (f: 0.000000, d: 1.000000e+06)
FPR6 43300000000f4240 (f: 1000000.000000, d: 4.503600e+15)
FPR7 4530000000000000 (f: 0.000000, d: 1.934281e+25)
FPR8 0072002400530069 (f: 5439593.000000, d: 1.602102e-306)
FPR9 006e0067006c0065 (f: 7077989.000000, d: 1.335114e-306)
FPR10 0074006f006e0048 (f: 7209032.000000, d: 1.780210e-306)
FPR11 006f006c00640065 (f: 6553701.000000, d: 1.379619e-306)
FPR12 3ff0000000000000 (f: 0.000000, d: 1.000000e+00)
FPR13 404d800000000000 (f: 0.000000, d: 5.900000e+01)
FPR14 0000000000000000 (f: 0.000000, d: 0.000000e+00)
FPR15 0000000000000000 (f: 0.000000, d: 0.000000e+00)
FPR16 0000000000000000 (f: 0.000000, d: 0.000000e+00)
FPR17 0000000000000000 (f: 0.000000, d: 0.000000e+00)
FPR18 0000000000000000 (f: 0.000000, d: 0.000000e+00)
FPR19 0000000000000000 (f: 0.000000, d: 0.000000e+00)
FPR20 0000000000000000 (f: 0.000000, d: 0.000000e+00)
FPR21 0000000000000000 (f: 0.000000, d: 0.000000e+00)
FPR22 0000000000000000 (f: 0.000000, d: 0.000000e+00)
FPR23 0000000000000000 (f: 0.000000, d: 0.000000e+00)
FPR24 0000000000000000 (f: 0.000000, d: 0.000000e+00)
FPR25 0000000000000000 (f: 0.000000, d: 0.000000e+00)
FPR26 0000000000000000 (f: 0.000000, d: 0.000000e+00)
FPR27 0000000000000000 (f: 0.000000, d: 0.000000e+00)
FPR28 0000000000000000 (f: 0.000000, d: 0.000000e+00)
FPR29 0000000000000000 (f: 0.000000, d: 0.000000e+00)
FPR30 0000000000000000 (f: 0.000000, d: 0.000000e+00)
FPR31 0000000000000000 (f: 0.000000, d: 0.000000e+00)
Target=2_60_20170718_357001 (AIX 7.1)
CPU=ppc64 (4 logical CPUs) (0x80000000 RAM)
----------- Stack Backtrace -----------
ffi_call+0x98 (0x09000000024D374C [jffi8605287488869115587.so+0x174c])
invokeArrayWithObjects_+0x57c (0x09000000024E8864 [jffi8605287488869115587.so+0x16864])
Java_com_kenai_jffi_Foreign_invokeArrayReturnInt+0x30 (0x09000000024E8B48 [jffi8605287488869115587.so+0x16b48])
(0x09000000006D2348 [libj9vm26.so+0x8a348])
(0x090000000065B5A8 [libj9vm26.so+0x135a8])
(0x090000000067CCAC [libj9vm26.so+0x34cac])
(0x09000000009CECE0 [libj9prt26.so+0x2ce0])
(0x090000000067CDDC [libj9vm26.so+0x34ddc])
(0x090000000065BCFC [libj9vm26.so+0x13cfc])
(0x090000000066241C [libj9vm26.so+0x1a41c])
JavaMain+0x3dc (0x0000010000003CC0 [java+0x3cc0])
_pthread_body+0xf0 (0x0900000000568E14 [libpthreads.a+0x3e14])
---------------------------------------
JVMDUMP039I Processing dump event "gpf", detail "" at 2018/05/03 23:24:28 - please wait.
JVMDUMP032I JVM requested System dump using '/home/tcr/core.20180503.232428.19267668.0001.dmp' in response to an event
Note: "Enable full CORE dump" in smit is set to FALSE and as a result there will be limited threading information in core file.
JVMDUMP010I System dump written to /home/tcr/core.20180503.232428.19267668.0001.dmp
JVMDUMP032I JVM requested Java dump using '/home/tcr/javacore.20180503.232428.19267668.0002.txt' in response to an event
JVMDUMP010I Java dump written to /home/tcr/javacore.20180503.232428.19267668.0002.txt
JVMDUMP032I JVM requested Snap dump using '/home/tcr/Snap.20180503.232428.19267668.0003.trc' in response to an event
JVMDUMP010I Snap dump written to /home/tcr/Snap.20180503.232428.19267668.0003.trc
JVMDUMP013I Processed dump event "gpf", detail "".

I'm not quite sure what's going wrong here, and my JNI knowledge is limited at best, but I can probably move from here and isolate what the issue is. I'm pretty sure it's not in libffi, but somewhere in the JNI C code, based on the backtrace, but I'm not sure why, or how to avoid it. I'm not sure if it's in my invocation of the JNI build. I can go a few places from here to experiment, but I'm mostly poking around in the dark here.

ARM Rock64 build failure

Trying to build on a rock64 board but receive the following error:

     [exec] libtool: compile:  cc -DHAVE_CONFIG_H -I. -I/home/rock64/jffi/jni/libffi -I. -I/home/rock64/jffi/jni/libffi/include -Iinclude -I/home/rock64/jffi/jni/libffi/src -I. -I/home/rock64/jffi/jni/libffi/include -Iinclude -I/home/rock64/jffi/jni/libffi/src -DFFI_MMAP_EXEC_WRIT -O2 -fno-omit-frame-pointer -fno-strict-aliasing -DNDEBUG -c /home/rock64/jffi/jni/libffi/src/aarch64/sysv.S  -fPIC -DPIC -o src/aarch64/.libs/sysv.o
     [exec] Makefile:1322: recipe for target 'src/aarch64/sysv.lo' failed
     [exec] make[3]: Leaving directory '/home/rock64/jffi/build/jni/libffi-arm-linux'
     [exec] Makefile:1577: recipe for target 'all-recursive' failed
     [exec] make[2]: Leaving directory '/home/rock64/jffi/build/jni/libffi-arm-linux'
     [exec] Makefile:726: recipe for target 'all' failed
     [exec] make[1]: Leaving directory '/home/rock64/jffi/build/jni/libffi-arm-linux'
     [exec] /home/rock64/jffi/jni/GNUmakefile:338: recipe for target '/home/rock64/jffi/build/jni/libffi-arm-linux/.libs/libffi_convenience.a' failed
     [exec] /home/rock64/jffi/jni/libffi/src/aarch64/sysv.S: Assembler messages:
     [exec] /home/rock64/jffi/jni/libffi/src/aarch64/sysv.S:105: Error: bad instruction `stp x29,x30,[sp,#-16]!'
     [exec] /home/rock64/jffi/jni/libffi/src/aarch64/sysv.S:107: Error: bad register expression
     [exec] /home/rock64/jffi/jni/libffi/src/aarch64/sysv.S:108: Error: bad register expression
     [exec] /home/rock64/jffi/jni/libffi/src/aarch64/sysv.S:110: Error: ARM register expected -- `mov x29,sp'
     [exec] /home/rock64/jffi/jni/libffi/src/aarch64/sysv.S:111: Error: bad register expression
     [exec] /home/rock64/jffi/jni/libffi/src/aarch64/sysv.S:114: Error: bad instruction `stp x21,x22,[sp,#0]'
     [exec] /home/rock64/jffi/jni/libffi/src/aarch64/sysv.S:115: Error: bad register expression

could not get native definition for type: POINTER on armv7l

OS and version used
Linux raspberrypi 4.14.79-v7+ #1159 SMP Sun Nov 4 17:50:20 GMT 2018 armv7l GNU/Linux

Problem description
I am using Azures Java IoT SDK on the above architecture. They are using jnr-unixsocket:0.19, but I manually upgraded to 0.22 but I still run into issues. I found this issue, which kinda relates to mine although I am on 32 bit. I cannot find which architectures are supported by this library, I am sorry if this issue does not belong here.

Here's a stacktrace of the problem I run into when using version 2.1.9 of this library (transitively through jnr-unixsocket:0.22).

If it is any help, I have an open issue at the Azure SDK too.

Please tell me if you need any more information or if this issue is better suited elsewhere.

Edit:

I'm guessing #59 is related to this and might solve my issue. Feel free to close this if that is the case and I'll keep an eye on that issue instead.

How to build win64 JNI?

Hi, I'm attempting to build the JNI library on win64, and cant seem to find any instructions on how to build.

Reading the GNUMakefile, I've managed to setup appropriate links to the win32 JDK JNI headers, but compilation is failing

Trying the cross-compile option on linux, I get the following failure:

/XXXX/git/jffi2/jni/jffi/Library.c: In function ‘Java_com_kenai_jffi_Foreign_dlopen’:
/XXXX/git/jffi2/jni/jffi/Library.c:91:19: error: implicit declaration of function ‘PathIsRelativeW’ [-Werror=implicit-function-declaration]
dwFlags = PathIsRelativeW(path) ? 0 : LOAD_WITH_ALTERED_SEARCH_PATH;
^~~~~~~~~~~~~~~

I've tried adding the following include, but that then gives a slew of other errors per the further below:
-I/usr/i686-w64-mingw32/include/

Any suggestions on how to resolve the above?

Thanks!

#if __INTRINSIC_PROLOG(__movsd)
^~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/i686-w64-mingw32/include/psdk_inc/intrin-impl.h:1932:1: error: this use of "defined" may not be portable [-Werror=expansion-to-defined]
/usr/i686-w64-mingw32/include/psdk_inc/intrin-impl.h:1932:1: error: this use of "defined" may not be portable [-Werror=expansion-to-defined]

Java 9+ with module system: could not locate stub library in jar file

I'm converting a project to use Java 11 using the module system. Using AdoptOpenJdk 11.0.4. Getting the following error.

Caused by: java.lang.UnsatisfiedLinkError: java.lang.UnsatisfiedLinkError: could not locate stub library in jar file. Tried [jni/Darwin/libjffi-1.2.dylib, /jni/Darwin/libjffi-1.2.dylib]
at [email protected]/com.kenai.jffi.internal.StubLoader.getStubLibraryStream(StubLoader.java:416)
at [email protected]/com.kenai.jffi.internal.StubLoader.loadFromJar(StubLoader.java:359)
at [email protected]/com.kenai.jffi.internal.StubLoader.load(StubLoader.java:262)
at [email protected]/com.kenai.jffi.internal.StubLoader.(StubLoader.java:453)

This seems to be related to how Java 9+ deals with getResourceAsStream. It doesn't allow accessing another jar's resources, so the files in jffi-1.2.19-native.jar are not resolved.

https://docs.oracle.com/javase/9/docs/api/java/lang/Class.html#getResourceAsStream-java.lang.String-

Using some jar command line hacks I was able to combine the contents of jffi-1.2.19-native.jar into the jffi-1.2.19.jar. As the resource is now in the same jar file the getResourceAsStream successfully finds the native library.

mkdir contents
cd contents
jar -xf ../jffi-1.2.19-native.jar
jar -xf ../jffi-1.2.19.jar
jar -cfm ../jffi-1.2.19.jar META-INF/MANIFEST.MF .

The other option would be to move the StubLoader.class or similar class into the jffi-1.2.19-native.jar and then try using that class when loading.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.