ignite-6743 DirectBuffer and DirectByteBuffer usages are removed Signed-off-by: Andrey Gura <[email protected]>
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/5fb4c136 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/5fb4c136 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/5fb4c136 Branch: refs/heads/ignite-zk Commit: 5fb4c136e619ee48c9c23cf89951095db04e7ed0 Parents: 264ba07 Author: Andrey Kuznetsov <[email protected]> Authored: Tue Dec 26 15:20:50 2017 +0300 Committer: Andrey Gura <[email protected]> Committed: Tue Dec 26 15:26:28 2017 +0300 ---------------------------------------------------------------------- .../wal/SegmentedRingByteBuffer.java | 4 +- .../internal/util/DirectBufferCleaner.java | 32 ++++++++++ .../apache/ignite/internal/util/GridUnsafe.java | 39 +++++++++++- .../util/ReflectiveDirectBufferCleaner.java | 64 ++++++++++++++++++++ .../util/UnsafeDirectBufferCleaner.java | 47 ++++++++++++++ .../ignite/internal/util/nio/GridNioServer.java | 6 +- 6 files changed, 185 insertions(+), 7 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/5fb4c136/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/SegmentedRingByteBuffer.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/SegmentedRingByteBuffer.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/SegmentedRingByteBuffer.java index a0209f9..43fe71a 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/SegmentedRingByteBuffer.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/SegmentedRingByteBuffer.java @@ -26,8 +26,8 @@ import java.util.List; import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; import java.util.concurrent.atomic.AtomicLongFieldUpdater; import org.apache.ignite.internal.processors.cache.persistence.DataStorageMetricsImpl; +import org.apache.ignite.internal.util.GridUnsafe; import org.apache.ignite.internal.util.typedef.internal.S; -import sun.nio.ch.DirectBuffer; import static java.nio.ByteBuffer.allocate; import static java.nio.ByteBuffer.allocateDirect; @@ -376,7 +376,7 @@ public class SegmentedRingByteBuffer { */ public void free() { if (mode == DIRECT || mode == MAPPED) - ((DirectBuffer)buf).cleaner().clean(); + GridUnsafe.cleanDirectBuffer(buf); } /** http://git-wip-us.apache.org/repos/asf/ignite/blob/5fb4c136/modules/core/src/main/java/org/apache/ignite/internal/util/DirectBufferCleaner.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/DirectBufferCleaner.java b/modules/core/src/main/java/org/apache/ignite/internal/util/DirectBufferCleaner.java new file mode 100644 index 0000000..2608d8a --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/util/DirectBufferCleaner.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.util; + +import java.nio.ByteBuffer; + +/** + * Cleaner interface for {@code java.nio.ByteBuffer}. + */ +public interface DirectBufferCleaner { + /** + * Cleans direct buffer. + * + * @param buf direct buffer. + */ + public void clean(ByteBuffer buf); +} http://git-wip-us.apache.org/repos/asf/ignite/blob/5fb4c136/modules/core/src/main/java/org/apache/ignite/internal/util/GridUnsafe.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/GridUnsafe.java b/modules/core/src/main/java/org/apache/ignite/internal/util/GridUnsafe.java index 55ff421..c4583a2 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/util/GridUnsafe.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/util/GridUnsafe.java @@ -18,6 +18,8 @@ package org.apache.ignite.internal.util; import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -29,7 +31,8 @@ import org.apache.ignite.IgniteSystemProperties; import sun.misc.JavaNioAccess; import sun.misc.SharedSecrets; import sun.misc.Unsafe; -import sun.nio.ch.DirectBuffer; + +import static org.apache.ignite.internal.util.IgniteUtils.majorJavaVersion; /** * <p>Wrapper for {@link sun.misc.Unsafe} class.</p> @@ -102,6 +105,12 @@ public abstract class GridUnsafe { /** {@link java.nio.Buffer#address} field offset. */ private static final long DIRECT_BUF_ADDR_OFF = bufferAddressOffset(); + /** Cleaner code for direct {@code java.nio.ByteBuffer}. */ + private static final DirectBufferCleaner DIRECT_BUF_CLEANER = + majorJavaVersion(System.getProperty("java.specification.version")) < 9 + ? new ReflectiveDirectBufferCleaner() + : new UnsafeDirectBufferCleaner(); + /** * Ensure singleton. */ @@ -117,7 +126,7 @@ public abstract class GridUnsafe { public static ByteBuffer wrapPointer(long ptr, int len) { ByteBuffer buf = nioAccess.newDirectByteBuffer(ptr, len, null); - assert buf instanceof DirectBuffer; + assert buf.isDirect(); buf.order(NATIVE_BYTE_ORDER); @@ -1344,6 +1353,32 @@ public abstract class GridUnsafe { } /** + * Invokes some method on {@code sun.misc.Unsafe} instance. + * + * @param mtd Method. + * @param args Arguments. + */ + public static Object invoke(Method mtd, Object... args) { + try { + return mtd.invoke(UNSAFE, args); + } + catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException("Unsafe invocation failed [cls=" + UNSAFE.getClass() + ", mtd=" + mtd + ']', e); + } + } + + /** + * Cleans direct {@code java.nio.ByteBuffer} + * + * @param buf Direct buffer. + */ + public static void cleanDirectBuffer(ByteBuffer buf) { + assert buf.isDirect(); + + DIRECT_BUF_CLEANER.clean(buf); + } + + /** * Returns unaligned flag. */ private static boolean unaligned() { http://git-wip-us.apache.org/repos/asf/ignite/blob/5fb4c136/modules/core/src/main/java/org/apache/ignite/internal/util/ReflectiveDirectBufferCleaner.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/ReflectiveDirectBufferCleaner.java b/modules/core/src/main/java/org/apache/ignite/internal/util/ReflectiveDirectBufferCleaner.java new file mode 100644 index 0000000..00ac787 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/util/ReflectiveDirectBufferCleaner.java @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.util; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.nio.ByteBuffer; + +/** + * {@link DirectBufferCleaner} implementation based on {@code sun.misc.Cleaner} and + * {@code sun.nio.ch.DirectBuffer.cleaner()} method. + * + * Mote: This implementation will not work on Java 9+. + */ +public class ReflectiveDirectBufferCleaner implements DirectBufferCleaner { + /** Cleaner method. */ + private final Method cleanerMtd; + + /** Clean method. */ + private final Method cleanMtd; + + /** */ + public ReflectiveDirectBufferCleaner() { + try { + cleanerMtd = Class.forName("sun.nio.ch.DirectBuffer").getMethod("cleaner"); + + } + catch (ClassNotFoundException | NoSuchMethodException e) { + throw new RuntimeException("No sun.nio.ch.DirectBuffer.cleaner() method found", e); + } + + try { + cleanMtd = Class.forName("sun.misc.Cleaner").getMethod("clean"); + } + catch (ClassNotFoundException | NoSuchMethodException e) { + throw new RuntimeException("No sun.misc.Cleaner.clean() method found", e); + } + } + + /** {@inheritDoc} */ + @Override public void clean(ByteBuffer buf) { + try { + cleanMtd.invoke(cleanerMtd.invoke(buf)); + } + catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException("Failed to invoke direct buffer cleaner", e); + } + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/5fb4c136/modules/core/src/main/java/org/apache/ignite/internal/util/UnsafeDirectBufferCleaner.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/UnsafeDirectBufferCleaner.java b/modules/core/src/main/java/org/apache/ignite/internal/util/UnsafeDirectBufferCleaner.java new file mode 100644 index 0000000..547f092 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/util/UnsafeDirectBufferCleaner.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.util; + +import java.lang.reflect.Method; +import java.nio.ByteBuffer; +import sun.misc.Unsafe; + +/** + * {@link DirectBufferCleaner} implementation based on {@code Unsafe.invokeCleaner} method. + * + * Note: This implementation will work only for Java 9+. + */ +public class UnsafeDirectBufferCleaner implements DirectBufferCleaner { + /** Cleaner method. */ + private final Method cleanerMtd; + + /** */ + public UnsafeDirectBufferCleaner() { + try { + cleanerMtd = Unsafe.class.getMethod("invokeCleaner", ByteBuffer.class); + } + catch (NoSuchMethodException e) { + throw new RuntimeException("Reflection failure: no sun.misc.Unsafe.invokeCleaner() method found", e); + } + } + + /** {@inheritDoc} */ + @Override public void clean(ByteBuffer buf) { + GridUnsafe.invoke(cleanerMtd, buf); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/5fb4c136/modules/core/src/main/java/org/apache/ignite/internal/util/nio/GridNioServer.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/nio/GridNioServer.java b/modules/core/src/main/java/org/apache/ignite/internal/util/nio/GridNioServer.java index 97f6020..3a88507 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/util/nio/GridNioServer.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/util/nio/GridNioServer.java @@ -56,6 +56,7 @@ import org.apache.ignite.internal.IgniteInternalFuture; import org.apache.ignite.internal.IgniteInterruptedCheckedException; import org.apache.ignite.internal.managers.communication.GridIoMessage; import org.apache.ignite.internal.util.GridConcurrentHashSet; +import org.apache.ignite.internal.util.GridUnsafe; import org.apache.ignite.internal.util.future.GridCompoundFuture; import org.apache.ignite.internal.util.nio.ssl.GridNioSslFilter; import org.apache.ignite.internal.util.tostring.GridToStringExclude; @@ -75,7 +76,6 @@ import org.apache.ignite.plugin.extensions.communication.MessageReader; import org.apache.ignite.plugin.extensions.communication.MessageWriter; import org.apache.ignite.thread.IgniteThread; import org.jetbrains.annotations.Nullable; -import sun.nio.ch.DirectBuffer; import static org.apache.ignite.internal.util.nio.GridNioSessionMetaKey.MSG_WRITER; import static org.apache.ignite.internal.util.nio.GridNioSessionMetaKey.NIO_OPERATION; @@ -2573,10 +2573,10 @@ public class GridNioServer<T> { if (directBuf) { if (ses.writeBuffer() != null) - ((DirectBuffer)ses.writeBuffer()).cleaner().clean(); + GridUnsafe.cleanDirectBuffer(ses.writeBuffer()); if (ses.readBuffer() != null) - ((DirectBuffer)ses.readBuffer()).cleaner().clean(); + GridUnsafe.cleanDirectBuffer(ses.readBuffer()); } closeKey(ses.key());
