I ran into this same problem using Java with Raspbian on a Pi 3 and found a posting from the Pi4J development team indicating that the problem is that when Pi4J is automatically installed, a copy of the wiringPi library is also installed and the copy of wiringPi in the installation package is old. I think this is a problem with Pi 3.
Also see https://www.raspberrypi.org/forums/viewtopic.php?t=182191#p1194857
The suggested work around is to cause the Pi4J component to dynamically load the wiringPi library rather than use the old version in the Pi4J package. This is done with a system properties addition. The command line to run an application must include the
-Dpi4j.linking=dynamic option as in:
java -Dpi4j.linking=dynamic <class to run>
I have set this using the JAVA_TOOL_OPTIONS environment variable so that I do not need to remember to specify the option on the command line when invoking
java to run my application.
I have a shell script that I do a
source Linux command on to set up my Java environment on Raspberry Pi. It contains the following directives for my Java environment.
The first directive is to set the
CLASSPATH environment variable by adding to the existing
CLASSPATH the directory where the Pi4J library jar files are located. The second is to provide the necessary directive to
java when running an application using Pi4J.
Addendum: Java classes, JVM, JNI (C Extensions) overview
Here is a brief overview about Java and the Java Virtual Machine and hardware specific libraries that use the Java Native Interface (JNI).
The Java compiler compiles the source code of Java classes into Java Virtual Machine byte code as class files. When the application is run, the Java Virtual Machine (JVM) loads the initial application class along with any additional classes needed for the application to run. In order to find the class files for the additional classes, the JVM uses the
CLASSPATH list of directories to search for the additional classes.
Some Java classes need to access specific hardware or operating system features that are not part of the standard Java installation. The Raspberry Pi hardware is an example. This requires that a Java class that is providing access to those specific features will need an additional component written in C or other programming language to provide an interface to those features or functionality.
The Pi4J classes used with Java on the Raspberry Pi provide a way to access the hardware pins of the Raspberry Pi. In order to do so, the Pi4J classes use the wiringPi library as the mechanism to gain access to the Pi hardware. So the Pi4J classes provide a Java interface to the wiringPi library which in turn provides the interface to the actual Pi hardware.
What this means is that in order for the Pi4J classes to work, they require access to the wiringPi library which is loaded long with the Pi4J classes. So the JVM needs to know that the library is required and how to find it so that when the Pi4J classes needed for your application are loaded, the needed wiringPi library is also loaded.
To make using the Pi4J library easy to install and use, the development team included in their install a copy of the wiringPi library. However if there are changes to the wiringPi library the version bundled with the Pi4J classes becomes out of date.
This answer is how to trigger the Pi4J classes and the JVM to use a version of the wiringPi library other than the one bundled with the Pi4J class install package.