• Stars
    star
    237
  • Rank 164,473 (Top 4 %)
  • Language
    Java
  • License
    GNU General Publi...
  • Created about 2 years ago
  • Updated 5 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

https://openjdk.org/projects/code-tools

Jextract

jextract is a tool which mechanically generates Java bindings from a native library headers. This tools leverages the clang C API in order to parse the headers associated with a given native library, and the generated Java bindings build upon the Foreign Function & Memory API. The jextract tool was originally developed in the context of Project Panama (and then made available in the Project Panama Early Access binaries).

Getting jextract

Pre-built binaries for jextract are periodically released here. These binaries are built from the master branch of this repo, and target the foreign memory access and function API in the latest mainline JDK (for which binaries can be found here).

Alternatively, to build jextract from the latest sources (which include all the latest updates and fixes) please refer to the building section below.


Using jextract

To understand how jextract works, consider the following C header file:

//point.h
struct Point2d {
    double x;
    double y;
};

double distance(struct Point2d);

We can run jextract, as follows:

jextract --source -t org.jextract point.h

We can then use the generated code as follows:

import java.lang.foreign.*;
import static org.jextract.point_h.*;
import org.jextract.Point2d;

class TestPoint {
    public static void main(String[] args) {
        try (var arena = Arena.openConfined()) {
           MemorySegment point = arena.allocate(Point2d.$LAYOUT());
           Point2d.x$set(point, 3d);
           Point2d.y$set(point, 4d);
           distance(point);
        }
    }
}

As we can see, the jextract tool generated a Point2d class, modelling the C struct, and a point_h class which contains static native function wrappers, such as distance. If we look inside the generated code for distance we can find the following:

static final FunctionDescriptor distance$FUNC = FunctionDescriptor.of(Constants$root.C_DOUBLE$LAYOUT,
    MemoryLayout.structLayout(
         Constants$root.C_DOUBLE$LAYOUT.withName("x"),
         Constants$root.C_DOUBLE$LAYOUT.withName("y")
    ).withName("Point2d")
);
static final MethodHandle distance$MH = RuntimeHelper.downcallHandle(
    "distance",
    constants$0.distance$FUNC
);

public static MethodHandle distance$MH() {
    return RuntimeHelper.requireNonNull(constants$0.distance$MH,"distance");
}
public static double distance ( MemorySegment x0) {
    var mh$ = distance$MH();
    try {
        return (double)mh$.invokeExact(x0);
    } catch (Throwable ex$) {
        throw new AssertionError("should not reach here", ex$);
    }
}

In other words, the jextract tool has generated all the required supporting code (MemoryLayout, MethodHandle and FunctionDescriptor) that is needed to call the underlying distance native function. For more examples on how to use the jextract tool with real-world libraries, please refer to the samples folder (building/running particular sample may require specific third-party software installation).

Command line options

The jextract tool includes several customization options. Users can select in which package the generated code should be emitted, and what the name of the main extracted class should be. If no package is specified, classes are generated in the unnamed package. If no name is specified for the main header class, then the header class name is derived from the header file name. For example, if jextract is run on foo.h, then foo_h will be the name of the main header class.

A complete list of all the supported options is given below:

Option Meaning
-D --define-macro <macro>=<value> define to (or 1 if omitted)
--header-class-name <name> name of the generated header class. If this option is not specified, then header class name is derived from the header file name. For example, class "foo_h" for header "foo.h".
-t, --target-package <package> target package name for the generated classes. If this option is not specified, then unnamed package is used.
-I, --include-dir <dir> append directory to the include search paths. Include search paths are searched in order. For example, if -I foo -I bar is specified, header files will be searched in "foo" first, then (if nothing is found) in "bar".
-l, --library <name | path> specify a library by platform-independent name (e.g. "GL") or by absolute path ("/usr/lib/libGL.so") that will be loaded by the generated class.
--output <path> specify where to place generated files
--source generate java sources instead of classfiles
--dump-includes <String> dump included symbols into specified file (see below)
--include-[function,constant,struct,union,typedef,var]<String> Include a symbol of the given name and kind in the generated bindings (see below). When one of these options is specified, any symbol that is not matched by any specified filters is omitted from the generated bindings.
--version print version information and exit

Additional clang options

Users can specify additional clang compiler options, by creating a file named compile_flags.txt in the current folder, as described here.

Filtering symbols

To allow for symbol filtering, jextract can generate a dump of all the symbols encountered in an header file; this dump can be manipulated, and then used as an argument file (using the @argfile syntax also available in other JDK tools) to e.g. generate bindings only for a subset of symbols seen by jextract. For instance, if we run jextract with as follows:

jextract --dump-includes includes.txt point.h

We obtain the following file (includes.txt):

#### Extracted from: point.h

--include-struct Point2d    # header: point.h
--include-function distance # header: point.h

This file can be passed back to jextract, as follows:

jextract -t org.jextract --source @includes.txt point.h

It is easy to see how this mechanism allows developers to look into the set of symbols seen by jextract while parsing, and then process the generated include file, so as to prevent code generation for otherwise unused symbols.


Building & Testing

jextract depends on the C libclang API. To build the jextract sources, the easiest option is to download LLVM binaries for your platform, which can be found here (a version >= 9 is required). Both the jextract tool and the bindings it generates depend heavily on the Foreign Function & Memory API, so a suitable jdk 20 distribution is also required.

Building older jextract versions

The master branch always tracks the latest version of the JDK. If you wish to build an older version of jextract, which targets an earlier version of the JDK you can do so by chercking out the appropriate branch. For example, to build a jextract tool which works against JDK 18:

git checkout jdk18

Over time, new branches will be added, each targeting a specific JDK version.

jextract can be built using gradle, as follows (on Windows, gradlew.bat should be used instead).

(Note: Run the Gradle build with a Java version appropriate for the Gradle version. For example, Gradle 7.5.1 supports JDK 18. Please checkout the Gradle compatibility matrix for the appropate JDK version needed for builds)

$ sh ./gradlew -Pjdk20_home=<jdk20_home_dir> -Pllvm_home=<libclang_dir> clean verify
Using a local installation of LLVM

While the recommended way is to use a release from the LLVM project, extract it then make llvm_home point to this directory, it may be possible to use a local installation instead.

E.g. on macOs the llvm_home can also be set as one of these locations :

  • /Library/Developer/CommandLineTools/usr/ if using Command Line Tools
  • /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/ if using XCode
  • $(brew --prefix llvm) if using the LLVM install from Homebrew

After building, there should be a new jextract folder under build. To run the jextract tool, simply run the jextract command in the bin folder:

$ build/jextract/bin/jextract
Expected a header file

Testing

The repository also contains a comprehensive set of tests, written using the jtreg test framework, which can be run as follows (again, on Windows, gradlew.bat should be used instead):

$ sh ./gradlew -Pjdk20_home=<jdk20_home_dir> -Pllvm_home=<libclang_dir> -Pjtreg_home=<jtreg_home> jtreg

Note: running jtreg task requires cmake to be available on the PATH.

More Repositories

1

jdk

JDK main-line development https://openjdk.org/projects/jdk
Java
17,577
star
2

jfx

JavaFX mainline development
C++
2,552
star
3

jmh

https://openjdk.org/projects/code-tools/jmh
Java
1,857
star
4

loom

https://openjdk.org/projects/loom
Java
1,828
star
5

jol

https://openjdk.org/projects/code-tools/jol
Java
810
star
6

jmc

Repository for OpenJDK Mission Control, a production time profiling and diagnostics tools suite. https://openjdk.org/projects/jmc
Java
786
star
7

valhalla

https://openjdk.org/projects/valhalla
Java
493
star
8

jcstress

https://openjdk.org/projects/code-tools/jcstress
Java
368
star
9

nashorn

https://openjdk.org/projects/nashorn
Java
361
star
10

panama-foreign

https://openjdk.org/projects/panama
Java
270
star
11

skara

https://openjdk.org/projects/skara
Java
199
star
12

jdk8u

https://wiki.openjdk.org/display/jdk8u
Java
187
star
13

wakefield

https://openjdk.org/projects/wakefield
Java
169
star
14

jdk17

https://openjdk.org/projects/jdk/17 released 2021-09-14
Java
164
star
15

amber

https://openjdk.org/projects/amber
Java
164
star
16

zgc

The Z Garbage Collector https://wiki.openjdk.org/display/zgc
Java
158
star
17

crac

https://openjdk.org/projects/crac
Java
157
star
18

amber-docs

https://openjdk.org/projects/amber
HTML
142
star
19

mobile

https://openjdk.org/projects/mobile
Java
134
star
20

jdk11u

https://openjdk.org/projects/jdk-updates
Java
130
star
21

shenandoah

https://openjdk.org/projects/shenandoah
Java
117
star
22

panama-vector

https://openjdk.org/projects/panama
Java
79
star
23

shenandoah-visualizer

https://openjdk.org/projects/shenandoah
Java
78
star
24

jdk17u

https://wiki.openjdk.org/display/JDKUpdates/JDK+17u
Java
76
star
25

aarch64-port

Port: AArch64 Project
Java
70
star
26

jdk21

https://openjdk.org/projects/jdk/21 released 2023-09-19
Java
65
star
27

asmtools

https://wiki.openjdk.org/display/CodeTools/asmtools
Java
60
star
28

valhalla-docs

https://openjdk.org/projects/valhalla
CSS
58
star
29

jdk16

https://openjdk.org/projects/jdk/16 released 2021-03-16
Java
57
star
30

guide

OpenJDK Developers' Guide https://openjdk.org/guide
Makefile
56
star
31

leyden

https://openjdk.org/projects/leyden
Java
55
star
32

jdk-sandbox

JDK Committers Sandbox
Java
55
star
33

jdk11u-dev

https://openjdk.org/projects/jdk-updates
Java
54
star
34

jtreg

https://openjdk.org/projects/code-tools/jtreg
Java
53
star
35

lilliput

https://openjdk.org/projects/lilliput
Java
47
star
36

riscv-port

https://openjdk.org/projects/riscv-port
Java
41
star
37

babylon

https://openjdk.org/projects/babylon
Java
41
star
38

jdk8

https://openjdk.org/projects/jdk8 released 2014-03-18
Java
40
star
39

jdk8u-dev

https://wiki.openjdk.org/display/jdk8u
Java
40
star
40

jdk15

https://openjdk.org/projects/jdk/15 released 2020-09-15
Java
39
star
41

jdk19

https://openjdk.org/projects/jdk/19 released 2022-09-20
Java
39
star
42

jmh-jdk-microbenchmarks

https://openjdk.org/projects/code-tools/jmh-jdk-microbenchmarks
Java
36
star
43

jdk17u-dev

https://openjdk.org/projects/jdk-updates
Java
32
star
44

jdk13

https://openjdk.org/projects/jdk/13 released 2019-09-17
Java
32
star
45

jdk21u

https://openjdk.org/projects/jdk-updates
Java
30
star
46

lanai

https://openjdk.org/projects/lanai
Java
27
star
47

jdk16u

https://openjdk.org/projects/jdk-updates last released 2021-07-20
Java
26
star
48

portola

https://openjdk.org/projects/portola
Java
23
star
49

jdk18

https://openjdk.org/projects/jdk/18 released 2022-03-22
Java
23
star
50

tsan

https://openjdk.org/projects/tsan
Java
22
star
51

duke

https://openjdk.org/projects/duke
Mathematica
21
star
52

jdk19u

https://openjdk.org/projects/jdk-updates last released 2023-01-17
Java
20
star
53

jdk11

https://openjdk.org/projects/jdk/11 released 2018-09-25
20
star
54

jdk20

https://openjdk.org/projects/jdk/20 released 2023-03-21
Java
20
star
55

jdk13u-dev

https://openjdk.org/projects/jdk-updates development (identical to jdk13u)
Java
17
star
56

jdk14u

https://openjdk.org/projects/jdk-updates last released 2020-07-14
Java
16
star
57

jcov

https://wiki.openjdk.org/display/CodeTools/jcov
Java
16
star
58

jdk12u

https://openjdk.org/projects/jdk-updates last released 2019-07-16
Java
16
star
59

metropolis

https://openjdk.org/projects/metropolis
Java
16
star
60

jdk20u

https://openjdk.org/projects/jdk-updates last released 2023-07-18
Java
15
star
61

jdk14

https://openjdk.org/projects/jdk/14 released 2020-03-17
Java
15
star
62

galahad

https://openjdk.org/projects/galahad
Java
15
star
63

jdk6

https://openjdk.org/projects/jdk6
Java
14
star
64

jfx-sandbox

OpenJFX Committers Sandbox
C++
13
star
65

jdk7u

https://wiki.openjdk.org/display/jdk7u last released 2022-07-19
Java
12
star
66

jtharness

https://wiki.openjdk.org/display/CodeTools/JT+Harness
Java
12
star
67

jfx11u

JavaFX 11 updates development
C++
12
star
68

jmc7

https://openjdk.org/projects/jmc
Java
12
star
69

jdk15u

https://wiki.openjdk.org/display/JDKUpdates/JDK+15u last released 2023-01-18
Java
11
star
70

jfx20u

JavaFX 20.x: last released 2023-07-18
C++
10
star
71

jdk7

https://openjdk.org/projects/jdk7 released 2011-07-28
Java
10
star
72

jemmy-v2

UI test automation library - v2
Java
9
star
73

jdk12

https://openjdk.org/projects/jdk/12 released 2019-03-19
8
star
74

webrevs

Automatically generated JSON files for webrevs
8
star
75

jdk15u-dev

https://openjdk.org/projects/jdk-updates development (identical to jdk15u)
Java
8
star
76

jfx21u

JavaFX 21 updates development
C++
7
star
77

jdk13u

https://wiki.openjdk.org/display/JDKUpdates/JDK+13u last released 2023-01-18
Java
7
star
78

client

JDK 16 era Client Libraries development
Java
7
star
79

jfx17u

JavaFX 17 updates development
C++
6
star
80

jdk18u

https://openjdk.org/projects/jdk-updates last released 2022-08-18
Java
6
star
81

playground

Repository for experimenting. May be synced and/or reset at any time without notice.
Java
6
star
82

lilliput-jdk17u

https://openjdk.org/projects/lilliput
Java
6
star
83

cr

https://openjdk.org/projects/skara
HTML
6
star
84

jdk22

https://openjdk.org/projects/jdk/22
Java
6
star
85

riscv-port-jdk17u

https://openjdk.org/projects/riscv-port
Java
6
star
86

sigtest

https://wiki.openjdk.org/display/CodeTools/sigtest
Java
5
star
87

shenandoah-jdk8u

https://openjdk.org/projects/shenandoah
Java
5
star
88

jdk11u-ri

JSR 384 Reference Implementation (Java SE 11) [not for production use]
Java
4
star
89

jdk9

https://openjdk.org/projects/jdk9 released 2017-09-21
Java
4
star
90

aarch32-port-jdk8u

https://openjdk.org/projects/aarch32-port
Java
4
star
91

jdk10u

https://openjdk.org/projects/jdk-updates last released 2018-07-17
3
star
92

friday-stats

https://openjdk.org/projects/code-tools/friday-stats
Java
3
star
93

jdk9u

https://openjdk.org/projects/jdk-updates last released 2018-01-16
Java
3
star
94

jfx12

JavaFX 12.x : last released 2019-07-19
C++
3
star
95

jfx13

JavaFX 13.x : last released 2020-01-15
C++
3
star
96

jmc-graphics

https://openjdk.org/projects/jmc
3
star
97

webrev

https://openjdk.org/projects/code-tools/webrev
Shell
2
star
98

riscv-port-jdk11u

https://openjdk.org/projects/riscv-port
Java
2
star
99

lilliput-jdk21u

https://openjdk.org/projects/lilliput
Java
2
star
100

jfx-tests

JavaFX Jemmy-based tests
Java
2
star