openhab / openhab-addons

Add-ons for openHAB
https://www.openhab.org/
Eclipse Public License 2.0
1.88k stars 3.59k forks source link

[mcp23017] java.lang.NoClassDefFoundError: Could not initialize class org.openhab.binding.mcp23017.internal.GPIODataHolder #4804

Closed mrumpf closed 5 years ago

mrumpf commented 5 years ago

Expected Behavior

No exception should occur, or at least a better error message to be able to resolve the issue.

Current Behavior

java.lang.NoClassDefFoundError: Could not initialize class org.openhab.binding.mcp23017.internal.GPIODataHolder
        at org.openhab.binding.mcp23017.handler.Mcp23017PinStateHolder.initializeOutputPin(Mcp23017PinStateHolder.java:71) ~[?:?]
        at org.openhab.binding.mcp23017.handler.Mcp23017PinStateHolder.getOutputPin(Mcp23017PinStateHolder.java:59) ~[?:?]
        at org.openhab.binding.mcp23017.handler.Mcp23017Handler.handleOutputCommand(Mcp23017Handler.java:108) ~[?:?]
        at org.openhab.binding.mcp23017.handler.Mcp23017Handler.handleCommand(Mcp23017Handler.java:80) ~[?:?]
        at org.eclipse.smarthome.core.thing.binding.BaseThingHandler.channelLinked(BaseThingHandler.java:233) ~[?:?]
        at org.openhab.binding.mcp23017.handler.Mcp23017Handler.channelLinked(Mcp23017Handler.java:212) ~[?:?]
        at org.eclipse.smarthome.core.thing.link.ThingLinkManager.lambda$0(ThingLinkManager.java:300) ~[?:?]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[?:?]
        at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[?:?]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) ~[?:?]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) ~[?:?]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:?]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:?]
        at java.lang.Thread.run(Thread.java:748) [?:?]

Possible Solution

Steps to Reproduce (for Bugs)

  1. Add the item and things configuration below
  2. Try to switch one of the output pins

Context

Your Environment

OpenHAB 2.4 with MCP23017 binding on Raspbian (Debian 9.6)

Thing definition

Thing mcp23017:mcp23017:chipA  "MCP23017 chip A" [address=20,bus=1] {
    Type output_pin : output#A0 [default_state="LOW"]
    Type output_pin : output#A1 [default_state="LOW"]
    Type output_pin : output#A2 [default_state="LOW"]
    Type output_pin : output#A3 [default_state="LOW"]
    Type output_pin : output#A4 [default_state="LOW"]
    Type output_pin : output#A5 [default_state="LOW"]
    Type output_pin : output#A6 [default_state="LOW"]
    Type output_pin : output#A7 [default_state="LOW"]
    Type output_pin : output#B0 [default_state="LOW"]
    Type output_pin : output#B1 [default_state="LOW"]
    Type output_pin : output#B2 [default_state="LOW"]
    Type output_pin : output#B3 [default_state="LOW"]
    Type output_pin : output#B4 [default_state="LOW"]
    Type output_pin : output#B5 [default_state="LOW"]
    Type output_pin : output#B6 [default_state="LOW"]
    Type output_pin : output#B7 [default_state="LOW"]
}

Item definition

Switch FF_A0 "Rolladen A0" (FF_Hallway,gShutter) { channel="mcp23017:mcp23017:chipA:output#A0" }
Switch FF_A1 "Rolladen A1" (FF_Hallway,gShutter) { channel="mcp23017:mcp23017:chipA:output#A1" }
Switch FF_A2 "Rolladen A2" (FF_Hallway,gShutter) { channel="mcp23017:mcp23017:chipA:output#A2" }
Switch FF_A3 "Rolladen A3" (FF_Hallway,gShutter) { channel="mcp23017:mcp23017:chipA:output#A3" }
Switch FF_A4 "Rolladen A4" (FF_Hallway,gShutter) { channel="mcp23017:mcp23017:chipA:output#A4" }
Switch FF_A5 "Rolladen A5" (FF_Hallway,gShutter) { channel="mcp23017:mcp23017:chipA:output#A5" }
Switch FF_A6 "Rolladen A6" (FF_Hallway,gShutter) { channel="mcp23017:mcp23017:chipA:output#A6" }
Switch FF_A7 "Rolladen A7" (FF_Hallway,gShutter) { channel="mcp23017:mcp23017:chipA:output#A7" }

Switch FF_B0 "Rolladen B0" (FF_Hallway,gShutter) { channel="mcp23017:mcp23017:chipA:output#B0" }
Switch FF_B1 "Rolladen B1" (FF_Hallway,gShutter) { channel="mcp23017:mcp23017:chipA:output#B1" }
Switch FF_B2 "Rolladen B2" (FF_Hallway,gShutter) { channel="mcp23017:mcp23017:chipA:output#B2" }
Switch FF_B3 "Rolladen B3" (FF_Hallway,gShutter) { channel="mcp23017:mcp23017:chipA:output#B3" }
Switch FF_B4 "Rolladen B4" (FF_Hallway,gShutter) { channel="mcp23017:mcp23017:chipA:output#B4" }
Switch FF_B5 "Rolladen B5" (FF_Hallway,gShutter) { channel="mcp23017:mcp23017:chipA:output#B5" }
Switch FF_B6 "Rolladen B6" (FF_Hallway,gShutter) { channel="mcp23017:mcp23017:chipA:output#B6" }
Switch FF_B7 "Rolladen B7" (FF_Hallway,gShutter) { channel="mcp23017:mcp23017:chipA:output#B7" }
mrumpf commented 5 years ago

Looking at the source code shows that the class GPIODataHolder has a static initializer: https://github.com/openhab/openhab2-addons/blob/master/addons/binding/org.openhab.binding.mcp23017/src/main/java/org/openhab/binding/mcp23017/internal/GPIODataHolder.java When the statement in this initializer fails, the NoClassDefFountError is thrown. An improvement could be to wrap the call to the Pi4j library with a try-catch block and log the error.

mrumpf commented 5 years ago

When I run the example: https://github.com/Pi4J/pi4j/blob/master/pi4j-example/src/main/java/NonPrivilegedGpioExample.java on my Raspberry Pi 3 B+

It dumps the following message on the console:

root@raspberrypi:~/pi4j# java -cp pi4j-1.1/lib/pi4j-core.jar:. NonPrivilegedGpioExample
<--Pi4J--> Non-Privileged GPIO Example ... started.
Unable to determine hardware version. I see: Hardware   : BCM2835
,
 - expecting BCM2708 or BCM2709.
If this is a genuine Raspberry Pi then please report this
to projects@drogon.net. If this is not a Raspberry Pi then you
are on your own as wiringPi is designed to support the
Raspberry Pi ONLY.

The Pi4j library issue discusses the topic here: https://github.com/Pi4J/pi4j/issues/319

After updating the library to version 1.2-SNAPSHOT this error went away, but revealed that WiringPi was missing on my RaspberryPi.

<--Pi4J--> Non-Privileged GPIO Example ... started.
Feb 05, 2019 11:44:31 AM com.pi4j.util.NativeLibraryLoader load
SEVERE: Unable to load [libpi4j.so] using path: [/lib/raspberrypi/dynamic/libpi4j.so]
java.lang.UnsatisfiedLinkError: /tmp/libpi4j3979346242306016496.so: libwiringPi.so: cannot open shared object file: No such file or directory
    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.pi4j.util.NativeLibraryLoader.loadLibraryFromClasspath(NativeLibraryLoader.java:159)
    at com.pi4j.util.NativeLibraryLoader.load(NativeLibraryLoader.java:105)
    at com.pi4j.wiringpi.GpioUtil.<clinit>(GpioUtil.java:64)
    at NonPrivilegedGpioExample.main(NonPrivilegedGpioExample.java:50)

Exception in thread "main" java.lang.UnsatisfiedLinkError: com.pi4j.wiringpi.GpioUtil.isPrivilegedAccessRequired()Z
    at com.pi4j.wiringpi.GpioUtil.isPrivilegedAccessRequired(Native Method)
    at NonPrivilegedGpioExample.main(NonPrivilegedGpioExample.java:50)

After installing it apt-get install wiringpi the example started successfully. I updated the MCP23017 Wiki page with a "Dependencies" section to make it clear that the library is required: #4806

mrumpf commented 5 years ago

Since June 2018 people ask the maintainer for a 1.2 release of the library: https://github.com/Pi4J/pi4j/issues/418 Unfortunately he seems to be unresponsive. I suggest to simply commit the 1.2-SNAPSHOT libraries to the lib folder of the mcp23017 binding.

cweitkamp commented 5 years ago

Pi4J version 1.2 has been released: PR #5014.