Repository: netty/netty
Issue: Unable to initialize PlatformDependent0 due to lack of sun.misc.Unsafe in classpath
Labels: defect

When trying to use [Vertx](http://vertx.io) in OSGi, I bumped into the following error. Initially I got: 
```[FelixStartLevel] DEBUG io.netty.util.internal.logging.InternalLoggerFactory - Using SLF4J as the default logging framework
[FelixStartLevel] DEBUG io.netty.util.ResourceLeakDetector - -Dio.netty.leakDetection.level: simple
[FelixStartLevel] DEBUG io.netty.util.ResourceLeakDetector - -Dio.netty.leakDetection.maxRecords: 4
[FelixStartLevel] DEBUG io.netty.channel.MultithreadEventLoopGroup - -Dio.netty.eventLoopThreads: 16
[FelixStartLevel] DEBUG io.netty.util.internal.PlatformDependent0 - java.nio.Buffer.address: available
[FelixStartLevel] DEBUG io.netty.util.internal.PlatformDependent - Java version: 8
[FelixStartLevel] DEBUG io.netty.util.internal.PlatformDependent - -Dio.netty.noUnsafe: false
[FelixStartLevel] DEBUG io.netty.util.internal.PlatformDependent - sun.misc.Unsafe: unavailable (io.netty.tryUnsafe/org.jboss.netty.tryUnsafe)
[FelixStartLevel] DEBUG io.netty.util.internal.PlatformDependent - maxDirectMemory: 3717201920 bytes (maybe)
[FelixStartLevel] ERROR debug - [debug(1)] The debugNetty method has thrown an exception
java.lang.NoClassDefFoundError: Could not initialize class io.netty.util.internal.PlatformDependent0
	at io.netty.util.internal.PlatformDependent.<clinit>(PlatformDependent.java:101)
	at io.netty.util.ConstantPool.<init>(ConstantPool.java:32)
	at io.netty.util.Signal$1.<init>(Signal.java:27)
	at io.netty.util.Signal.<clinit>(Signal.java:27)
	at io.netty.util.concurrent.DefaultPromise.<clinit>(DefaultPromise.java:42)
	at io.netty.util.concurrent.MultithreadEventExecutorGroup.<init>(MultithreadEventExecutorGroup.java:36)
	at io.netty.util.concurrent.MultithreadEventExecutorGroup.<init>(MultithreadEventExecutorGroup.java:58)
	at io.netty.util.concurrent.MultithreadEventExecutorGroup.<init>(MultithreadEventExecutorGroup.java:47)
	at io.netty.channel.MultithreadEventLoopGroup.<init>(MultithreadEventLoopGroup.java:58)
	at io.netty.channel.nio.NioEventLoopGroup.<init>(NioEventLoopGroup.java:77)
	at io.netty.channel.nio.NioEventLoopGroup.<init>(NioEventLoopGroup.java:72)
	at io.netty.channel.nio.NioEventLoopGroup.<init>(NioEventLoopGroup.java:59)
	at io.vertx.core.impl.VertxImpl.<init>(VertxImpl.java:133)
	at io.vertx.core.impl.VertxImpl.<init>(VertxImpl.java:122)
	at io.vertx.core.impl.VertxImpl.<init>(VertxImpl.java:118)
	at io.vertx.core.impl.VertxFactoryImpl.vertx(VertxFactoryImpl.java:34)
	at io.vertx.core.Vertx.vertx(Vertx.java:80)
```

I tried to debug the situation and found that the fact that sun.misc.Unsafe is not available could be an issue (see [#272](https://github.com/netty/netty/issues/272)), I tried to set the system property `io.netty.tryUnsafe` to `false`, to no avail (the stacktrace above has `io.netty.tryUnsafe` set to `false`). 

When I copy the PlatformDependent0 class to the debug package so I have control, I get the following:
```
[FelixStartLevel] DEBUG debug.PlatformDependent0 - java.nio.Buffer.address: available
[FelixStartLevel] ERROR debug - [debug(1)] Error during instantiation of the implementation object
java.lang.NoClassDefFoundError: sun/misc/Unsafe
	at debug.PlatformDependent0$2.run(PlatformDependent0.java:86)
	at java.security.AccessController.doPrivileged(Native Method)
	at debug.PlatformDependent0.<clinit>(PlatformDependent0.java:82)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:264)
	at DebugNetty.<init>(DebugNetty.java:23)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at java.lang.Class.newInstance(Class.java:442)
	at org.apache.felix.scr.impl.manager.SingleComponentManager.createImplementationObject(SingleComponentManager.java:236)
	at org.apache.felix.scr.impl.manager.SingleComponentManager.createComponent(SingleComponentManager.java:108)
	at org.apache.felix.scr.impl.manager.SingleComponentManager.getService(SingleComponentManager.java:906)
	at org.apache.felix.scr.impl.manager.SingleComponentManager.getServiceInternal(SingleComponentManager.java:879)
	at org.apache.felix.scr.impl.manager.AbstractComponentManager.activateInternal(AbstractComponentManager.java:748)
	at org.apache.felix.scr.impl.manager.AbstractComponentManager.enableInternal(AbstractComponentManager.java:674)
	at org.apache.felix.scr.impl.manager.AbstractComponentManager.enable(AbstractComponentManager.java:429)
	at org.apache.felix.scr.impl.manager.ConfigurableComponentHolder.enableComponents(ConfigurableComponentHolder.java:657)
	at org.apache.felix.scr.impl.BundleComponentActivator.initialEnable(BundleComponentActivator.java:341)
	at org.apache.felix.scr.impl.Activator.loadComponents(Activator.java:403)
	at org.apache.felix.scr.impl.Activator.access$200(Activator.java:54)
	at org.apache.felix.scr.impl.Activator$ScrExtension.start(Activator.java:278)
	at org.apache.felix.utils.extender.AbstractExtender.createExtension(AbstractExtender.java:259)
	at org.apache.felix.utils.extender.AbstractExtender.modifiedBundle(AbstractExtender.java:232)
	at org.osgi.util.tracker.BundleTracker$Tracked.customizerModified(BundleTracker.java:482)
	at org.osgi.util.tracker.BundleTracker$Tracked.customizerModified(BundleTracker.java:415)
	at org.osgi.util.tracker.AbstractTracked.track(AbstractTracked.java:232)
	at org.osgi.util.tracker.BundleTracker$Tracked.bundleChanged(BundleTracker.java:444)
	at org.apache.felix.framework.util.EventDispatcher.invokeBundleListenerCallback(EventDispatcher.java:916)
	at org.apache.felix.framework.util.EventDispatcher.fireEventImmediately(EventDispatcher.java:835)
	at org.apache.felix.framework.util.EventDispatcher.fireBundleEvent(EventDispatcher.java:517)
	at org.apache.felix.framework.Felix.fireBundleEvent(Felix.java:4541)
	at org.apache.felix.framework.Felix.startBundle(Felix.java:2172)
	at org.apache.felix.framework.Felix.setActiveStartLevel(Felix.java:1371)
	at org.apache.felix.framework.FrameworkStartLevelImpl.run(FrameworkStartLevelImpl.java:308)
	at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ClassNotFoundException: sun.misc.Unsafe not found by debug [29]
	at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1574)
	at org.apache.felix.framework.BundleWiringImpl.access$400(BundleWiringImpl.java:79)
	at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:2018)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	... 37 more
```
which indeed shows the root cause is sun.misc.Unsafe not being found. The version of Netty used is 4.1.6.Final. Exposing sun.misc through OSGi solves the problem, but that is not a viable solution in the long term.

Please advise.

Issue comments:
One of the fields in PlatformDependent references PlatformDependent0 directly without being guarded by hasUnsafe.

Is the issue you don't want to see the warning message, or is this causing a functional issue?

@johnou - which field do you think is an issue?

@johnou - your commit https://github.com/johnou/netty/commit/cff208eb2895134a487424b4b2dcd9c5cafc9f99 changes the initialization of `BYTE_ARRAY_BASE_OFFSET` ... is their a problem with just using the default as set by `PlatformDependent0` (currently `-1`)? IIRC it is assumed whenever this value is used it is guarded  by an unsafe check ... did we miss a case?

@Scottmitch BYTE_ARRAY_BASE_OFFSET is set to -1 in PlatformDependent0 if unsafe is unavailable, and if unsafe is unavailable, so is PlatformDependent0, therefore we need to use indirection when accessing it (cannot be directly how it is now otherwise PlatformDependent cannot be loaded)..

java.lang.NoClassDefFoundError: Could not initialize class io.netty.util.internal.PlatformDependent0
    at io.netty.util.internal.PlatformDependent.<clinit>(PlatformDependent.java:101)

@Scottmitch: this causes a functional issue in environments where sun.misc is not available, which is the default in OSGi frameworks
I can make a pull request tomorrow, extracting the BYTE_ARRAY_BASE_OFFSET initialization into a method like addressSize0 does for ADDRESS_SIZE. Would that be something you could consider including?

Edit: [johnou@cff208e](https://github.com/johnou/netty/commit/cff208eb2895134a487424b4b2dcd9c5cafc9f99) should fix the issue

@jellenelis see https://github.com/netty/netty/pull/5988

Thanks for the quick responses, BTW!

thanks for clarifying ... we want to avoid loading `PlatformDependent0` if the `Unsafe` interface is not available.

Fixed by https://github.com/netty/netty/pull/5988

Hello I'm using netty version 4.1.8.Final on Apache Felix and still suffer from the same problem!
lb:
0|Active     |    0|System Bundle (5.4.0)|5.4.0
    1|Active     |    1|Guava: Google Core Libraries for Java (18.0.0)|18.0.0
    2|Active     |    1|Jackson-annotations (2.7.0)|2.7.0
    3|Active     |    1|Jackson-core (2.7.4)|2.7.4
    4|Active     |    1|jackson-databind (2.7.4)|2.7.4
    5|Active     |    1|com.github.shumy.leffe-wg (1.0.0)|1.0.0
    6|Active     |    1|Netty/Buffer (4.1.8.Final)|4.1.8.Final
    7|Active     |    1|Netty/Codec (4.1.8.Final)|4.1.8.Final
    8|Active     |    1|Netty/Codec/DNS (4.1.8.Final)|4.1.8.Final
    9|Active     |    1|Netty/Codec/HTTP (4.1.8.Final)|4.1.8.Final
   10|Active     |    1|Netty/Codec/HTTP2 (4.1.8.Final)|4.1.8.Final
   11|Active     |    1|Netty/Codec/Socks (4.1.8.Final)|4.1.8.Final
   12|Active     |    1|Netty/Common (4.1.8.Final)|4.1.8.Final
   13|Active     |    1|Netty/Handler (4.1.8.Final)|4.1.8.Final
   14|Active     |    1|Netty/Handler/Proxy (4.1.8.Final)|4.1.8.Final
   15|Active     |    1|Netty/Resolver (4.1.8.Final)|4.1.8.Final
   16|Active     |    1|Netty/Resolver/DNS (4.1.8.Final)|4.1.8.Final
   17|Active     |    1|Netty/Transport (4.1.8.Final)|4.1.8.Final
   18|Active     |    1|Apache Felix Configuration Admin Service (1.8.14)|1.8.14
   19|Active     |    1|Apache Felix Gogo Command (0.16.0)|0.16.0
   20|Active     |    1|Apache Felix Gogo Runtime (0.16.2)|0.16.2
   21|Active     |    1|Apache Felix Gogo Shell (0.12.0)|0.12.0
   22|Active     |    1|Apache Felix Declarative Services (2.0.8)|2.0.8
   23|Active     |    1|Xtend Runtime Library (2.11.0.v20170124-1424)|2.11.0.v20170124-1424
   24|Active     |    1|Xtend Macro Interfaces (2.11.0.v20170124-1424)|2.11.0.v20170124-1424
   25|Active     |    1|Xbase Runtime Library (2.11.0.v20170124-1424)|2.11.0.v20170124-1424
   26|Active     |    1|OPS4J Pax Logging - API (1.9.1)|1.9.1
   27|Active     |    1|Vert.x Core (3.4.1)|3.4.1

@shumy please open a new issue with an updated stacktrace.
@shumy also a reproducer would be nice.
New issue #6548
I run netty4.1.42 under jdk11.0.6 and reports java.lang.UnsupportedOperationException: sun.misc.Unsafe unavailable, I don't know how to solve it?

Pull request review comments:

Patch that resolved the issue:
diff --git a/common/src/main/java/io/netty/util/internal/PlatformDependent.java b/common/src/main/java/io/netty/util/internal/PlatformDependent.java
index 81348a06b67..320a63819e3 100644
--- a/common/src/main/java/io/netty/util/internal/PlatformDependent.java
+++ b/common/src/main/java/io/netty/util/internal/PlatformDependent.java
@@ -98,7 +98,7 @@ public final class PlatformDependent {
     private static final int DEFAULT_MAX_MPSC_CAPACITY =  MPSC_CHUNK_SIZE * MPSC_CHUNK_SIZE;
     private static final int MAX_ALLOWED_MPSC_CAPACITY = Pow2.MAX_POW2;
 
-    private static final long BYTE_ARRAY_BASE_OFFSET = PlatformDependent0.byteArrayBaseOffset();
+    private static final long BYTE_ARRAY_BASE_OFFSET = byteArrayBaseOffset0();
 
     private static final boolean HAS_JAVASSIST = hasJavassist0();
 
@@ -1378,6 +1378,13 @@ private static int addressSize0() {
         return PlatformDependent0.addressSize();
     }
 
+    private static long byteArrayBaseOffset0() {
+        if (!hasUnsafe()) {
+            return -1;
+        }
+        return PlatformDependent0.byteArrayBaseOffset();
+    }
+
     private static boolean equalsSafe(byte[] bytes1, int startPos1, byte[] bytes2, int startPos2, int length) {
         final int end = startPos1 + length;
         for (int i = startPos1, j = startPos2; i < end; ++i, ++j) {


Test patch: