This README is for the latest, possibly unreleased, version. For the documentation on the 2.x releases, check the releases/2.x
branch.
Bindings for SocketCAN's CAN_RAW, CAN_BCM and CAN_ISOTP sockets with full support for blocking and non-blocking IO. Non-blocking IO is possible using the epoll module, that provides an API very similar to Java's Selector API.
Implementing Java's SelectableChannel API is not possible with EPoll and SocketCAN due to various hardcoded assumptions in the JDK.
Yes! While feature development tends to happen in bursts around specific topics, issues and pull requests will always be answered. Dependencies will be updated occasionally. Releases are made mostly based on demand. The master branch is generally in a releasable state, if you need something released, just ask for it.
Pull requests are welcome!
This project is a wrapper around SocketCAN, which is a Linux kernel module that implements CAN communication. As such, only Linux can be supported. For this reason, the custom Selector will also only use epoll (Linux API for event-driven IO), as support for other OS' is not possible anyway.
The project uses dockcross to cross-compile its native components for various Linux supported platforms.
Currently, the full build process includes the following architectures:
x86_32
x86_64
armv6
armv7
armv7a
armv7l
(musl libc, linked statically)aarch64
riscv32
riscv64
The implementation can handle word sizes up to 64 bit and is byte order aware. If you need another architecture, feel free to ask for it! Alternatively read how to build another architecture down below.
Additionally, the following architectures are included specifically for Android:
android-arm
android-arm64
android-x86_64
android-x86_32
LD_LIBRARY_PATH
or configure the appropriate Java properties (See next section)CanChannels.new...Channel()
methodsNetworkDevice
using its static lookup(String)
methodbind(CanDevice)
methodUsage example can be found in the unit tests or in the related projects mentioned above.
Remember: JavaCAN is a fairly thin wrapper around Linux syscalls. Even though some aspects of the low-level C API are hidden, most Java APIs in this library will at some point call into a
(usually similarly named) C API and as such inherits all of its properties. For example RawCanChannel.close()
translates to a call to close()
on the underlying file descriptor, so their behaviour
should be identical. So if the behaviour of a certain API is unclear, a look into the man pages of related Linux syscalls might help. Feel free to still request additional documentation in the issues
on GitHub!
The library relies on several native (JNI) components. By default, these components are either loaded from the standard library path (LD_LIBRARY_PATH
/ java.library.path
) or are extracted from
the classpath into a temporary folder.
There are a few approaches to get the correct native libraries loaded:
LD_LIBRARY_PATH
environment variable or the java.library.path
property)javacan.native.javacan-<module>.path
property to tell JavaCAN the exact file system path where the native component is locatedjavacan.native.javacan-<module>.classpath
property to tell JavaCAN the exact location on the classpath where the native component is locatedFor applications that are intended to run on a single architecture or that build architecture-specific versions already, the simplest solution is to bundle the provided architecture-specific jar files matching the build architecture.
For applications supporting multiple architectures at once I'd recommend dynamically adding the architecture-specific jar file at runtime or to repackage the available native libraries and
dynamically configuring the javacan.native.javacan-<module>.path
properties in the CLI or before any JavaCAN classes are loaded.
The value for the <module>
placeholder used throughout this section is core
and if the EPoll support is used, an additional option with epoll
for <module>
is necessary.
While JavaCAN 2.x bundled the native components in its main artifacts, starting with the 3.x release series the native components are instead provided as separate jar files (classified by their architecture). This provides full control over which library is loaded, especially on architectures on which the JVM doesn't provide enough information for a reliable architecture detection. Programs using JavaCAN usually depend on specific architectures and thus can pull just the relevant components and nothing more.
For applications like test tools that don't really care about program size and don't need to support every possible architecture, starting with JavaCAN 3.3 *-arch-detect
modules are provided.
These modules bundle all prebuilt architectures and provide a function to automatically load the correct variant based on the os.arch
system property.
For example for the javacan-core
module you would instead depend on the javacan-core-arch-detect
module and then, somewhere early in your program, invoke JavaCANAutoDetect.initialize()
.
This will configure the necessary system property based on the architecture detection and eagerly initialize JavaCAN.
In case you have issues, have a look at the troubleshooting document.
For local compilation:
For cross compilation:
For tests:
CONFIG_CAN_ISOTP
enabled or the out-of-tree module)PATH
For usage:
CONFIG_CAN_ISOTP
enabled or the out-of-tree module)All architectures can be built in parallel with using the compileNativeAll
task:
./gradlew compileNativeAll
Alternatively there exist packageNativeFor*
tasks for all the bundled architectures. A special task is packageNativeForHost, which will use
the compiler toolchain on your machine instead of dockcross. This is primarily intended for unit tests, but can also be used to build on systems
that are not supported by dockcross.
All architectures allow their dockcross image to be overridden by properties like dockcross.image.<architecture>
. The linking
mode (dynamic
or static
) can also be overridden by properties like dockcross.link.<architecture>
.
Using the property javacan.extra-archs
additional architectures can be defined as a comma-separated list. The values will be used as the
jar classifier. These additional architectures will also require manually setting configuring the dockcross image and linking mode using the
previously mentioned properties.