Add DetectionUtil which replaces UnsafeDetectUtil / Improve SpdyHeaderBlockJZlibDecompressor
This commit is contained in:
parent
34e328f606
commit
cf02ad2a1e
@ -15,32 +15,15 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.handler.codec.spdy;
|
package io.netty.handler.codec.spdy;
|
||||||
|
|
||||||
import java.util.zip.Deflater;
|
|
||||||
|
|
||||||
import io.netty.buffer.ChannelBuffer;
|
import io.netty.buffer.ChannelBuffer;
|
||||||
|
import io.netty.util.internal.DetectionUtil;
|
||||||
|
|
||||||
abstract class SpdyHeaderBlockCompressor {
|
abstract class SpdyHeaderBlockCompressor {
|
||||||
|
|
||||||
private static final boolean USE_ZLIB;
|
|
||||||
|
|
||||||
static {
|
|
||||||
boolean java7 = false;
|
|
||||||
try {
|
|
||||||
Deflater.class.getDeclaredMethod(
|
|
||||||
"deflate",
|
|
||||||
new Class<?>[] { byte[].class, int.class, int.class, int.class });
|
|
||||||
java7 = true;
|
|
||||||
} catch (Exception e) {
|
|
||||||
// Ignore
|
|
||||||
}
|
|
||||||
|
|
||||||
USE_ZLIB = java7;
|
|
||||||
}
|
|
||||||
|
|
||||||
static SpdyHeaderBlockCompressor newInstance(
|
static SpdyHeaderBlockCompressor newInstance(
|
||||||
int compressionLevel, int windowBits, int memLevel) {
|
int compressionLevel, int windowBits, int memLevel) {
|
||||||
|
|
||||||
if (USE_ZLIB) {
|
if (DetectionUtil.javaVersion() >= 7) {
|
||||||
return new SpdyHeaderBlockZlibCompressor(compressionLevel);
|
return new SpdyHeaderBlockZlibCompressor(compressionLevel);
|
||||||
} else {
|
} else {
|
||||||
return new SpdyHeaderBlockJZlibCompressor(
|
return new SpdyHeaderBlockJZlibCompressor(
|
||||||
|
@ -50,14 +50,36 @@ class SpdyHeaderBlockJZlibDecompressor extends SpdyHeaderBlockDecompressor {
|
|||||||
z.next_out_index = 0;
|
z.next_out_index = 0;
|
||||||
z.avail_out = out.length;
|
z.avail_out = out.length;
|
||||||
|
|
||||||
|
loop: for (;;) {
|
||||||
|
// Decompress 'in' into 'out'
|
||||||
int resultCode = z.inflate(JZlib.Z_SYNC_FLUSH);
|
int resultCode = z.inflate(JZlib.Z_SYNC_FLUSH);
|
||||||
|
if (z.next_out_index > 0) {
|
||||||
|
decompressed.writeBytes(out, 0, z.next_out_index);
|
||||||
|
z.avail_out = out.length;
|
||||||
|
}
|
||||||
|
z.next_out_index = 0;
|
||||||
|
|
||||||
if (resultCode == JZlib.Z_NEED_DICT) {
|
switch (resultCode) {
|
||||||
|
case JZlib.Z_NEED_DICT:
|
||||||
resultCode = z.inflateSetDictionary(SPDY_DICT, SPDY_DICT.length);
|
resultCode = z.inflateSetDictionary(SPDY_DICT, SPDY_DICT.length);
|
||||||
if (resultCode != JZlib.Z_OK) {
|
if (resultCode != JZlib.Z_OK) {
|
||||||
throw new CompressionException("ZStream dictionary failure");
|
throw new CompressionException("failed to set the dictionary: " + resultCode);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case JZlib.Z_STREAM_END:
|
||||||
|
// Do not decode anymore.
|
||||||
|
z.inflateEnd();
|
||||||
|
break loop;
|
||||||
|
case JZlib.Z_OK:
|
||||||
|
break;
|
||||||
|
case JZlib.Z_BUF_ERROR:
|
||||||
|
if (z.avail_in <= 0) {
|
||||||
|
break loop;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new CompressionException("decompression failure: " + resultCode);
|
||||||
}
|
}
|
||||||
z.inflate(JZlib.Z_SYNC_FLUSH);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (z.next_out_index > 0) {
|
if (z.next_out_index > 0) {
|
||||||
|
@ -13,52 +13,65 @@
|
|||||||
* License for the specific language governing permissions and limitations
|
* License for the specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
package io.netty.util;
|
package io.netty.util.internal;
|
||||||
|
|
||||||
import java.security.AccessController;
|
import java.security.AccessController;
|
||||||
import java.security.PrivilegedActionException;
|
import java.security.PrivilegedActionException;
|
||||||
import java.security.PrivilegedExceptionAction;
|
import java.security.PrivilegedExceptionAction;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.zip.Deflater;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility which checks if {@value #UNSAFE} class can be found in the classpath
|
* Utility that detects various properties specific to the current runtime
|
||||||
* and that it can be accessed using "theUnsafe" field which is not true for all platforms, i.e Android
|
* environment, such as Java version and the availability of the
|
||||||
* where it is called "THE_ONE".
|
* {@code sun.misc.Unsafe} object.
|
||||||
*/
|
*/
|
||||||
public final class UnsafeDetectUtil {
|
public final class DetectionUtil {
|
||||||
|
|
||||||
private static final String THE_UNSAFE = "theUnsafe";
|
private static final int JAVA_VERSION = javaVersion0();
|
||||||
private static final String UNSAFE = "sun.misc.Unsafe";
|
private static final boolean HAS_UNSAFE = hasUnsafe(AtomicInteger.class.getClassLoader());
|
||||||
private static final boolean UNSAFE_FOUND = isUnsafeFound(AtomicInteger.class.getClassLoader());
|
|
||||||
|
|
||||||
public static boolean isUnsafeFound(ClassLoader loader) {
|
public static boolean hasUnsafe() {
|
||||||
try {
|
return HAS_UNSAFE;
|
||||||
Class<?> unsafeClazz = Class.forName(UNSAFE, true, loader);
|
|
||||||
return hasUnsafeField(unsafeClazz);
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
return false;
|
|
||||||
} catch (SecurityException e) {
|
|
||||||
return false;
|
|
||||||
} catch (PrivilegedActionException e) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int javaVersion() {
|
||||||
|
return JAVA_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean hasUnsafe(ClassLoader loader) {
|
||||||
|
try {
|
||||||
|
Class<?> unsafeClazz = Class.forName("sun.misc.Unsafe", true, loader);
|
||||||
|
return hasUnsafeField(unsafeClazz);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean hasUnsafeField(final Class<?> unsafeClass) throws PrivilegedActionException {
|
private static boolean hasUnsafeField(final Class<?> unsafeClass) throws PrivilegedActionException {
|
||||||
return AccessController.doPrivileged(new PrivilegedExceptionAction<Boolean>() {
|
return AccessController.doPrivileged(new PrivilegedExceptionAction<Boolean>() {
|
||||||
|
@Override
|
||||||
public Boolean run() throws Exception {
|
public Boolean run() throws Exception {
|
||||||
unsafeClass.getDeclaredField(THE_UNSAFE);
|
unsafeClass.getDeclaredField("theUnsafe");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isUnsafeFound() {
|
private static int javaVersion0() {
|
||||||
return UNSAFE_FOUND;
|
try {
|
||||||
|
Deflater.class.getDeclaredField("SYNC_FLUSH");
|
||||||
|
return 7;
|
||||||
|
} catch (Exception e) {
|
||||||
|
// Ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
private UnsafeDetectUtil() {
|
return 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DetectionUtil() {
|
||||||
// only static method supported
|
// only static method supported
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -18,15 +18,13 @@ package io.netty.util.internal;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.concurrent.BlockingQueue;
|
import java.util.concurrent.BlockingQueue;
|
||||||
|
|
||||||
import io.netty.util.UnsafeDetectUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This factory should be used to create the "optimal" {@link BlockingQueue}
|
* This factory should be used to create the "optimal" {@link BlockingQueue}
|
||||||
* instance for the running JVM.
|
* instance for the running JVM.
|
||||||
*/
|
*/
|
||||||
public final class QueueFactory {
|
public final class QueueFactory {
|
||||||
|
|
||||||
private static final boolean useUnsafe = UnsafeDetectUtil.isUnsafeFound(QueueFactory.class.getClassLoader());
|
private static final boolean useUnsafe = DetectionUtil.hasUnsafe();
|
||||||
|
|
||||||
private QueueFactory() {
|
private QueueFactory() {
|
||||||
// only use static methods!
|
// only use static methods!
|
||||||
|
Loading…
Reference in New Issue
Block a user