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