Add DetectionUtil which replaces UnsafeDetectUtil / Improve SpdyHeaderBlockJZlibDecompressor

This commit is contained in:
Trustin Lee 2012-03-07 19:45:56 +09:00
parent 34e328f606
commit cf02ad2a1e
4 changed files with 72 additions and 56 deletions

View File

@ -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(

View File

@ -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) {

View File

@ -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) {
try {
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 boolean hasUnsafe() {
return HAS_UNSAFE;
}
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 {
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 UnsafeDetectUtil() {
private static int javaVersion0() {
try {
Deflater.class.getDeclaredField("SYNC_FLUSH");
return 7;
} catch (Exception e) {
// Ignore
}
return 6;
}
private DetectionUtil() {
// only static method supported
}
}

View File

@ -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!