`

NativeHandler

 
阅读更多
/**
* Copyright (c) 2008 Greg Whalin
* All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the BSD license
*
* This library is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE.
*
* You should have received a copy of the BSD License along with this
* library.
*
* @author Greg Whalin <greg@meetup.com>
*/
package com.yulong.memcached;

import java.util.Date;
import org.apache.log4j.Logger;

/**
* Handle encoding standard Java types directly which can result in significant
* memory savings:
*
* Currently the Memcached driver for Java supports the setSerialize() option.
* This can increase performance in some situations but has a few issues:
*
* Code that performs class casting will throw ClassCastExceptions when
* setSerialize is enabled. For example:
*
*     mc.set( "foo", new Integer( 1 ) ); Integer output = (Integer)mc.get("foo");
*
* Will work just file when setSerialize is true but when its false will just throw
* a ClassCastException.
*
* Also internally it doesn't support Boolean and since toString is called wastes a
* lot of memory and causes additional performance issue.  For example an Integer
* can take anywhere from 1 byte to 10 bytes.
*
* Due to the way the memcached slab allocator works it seems like a LOT of wasted
* memory to store primitive types as serialized objects (from a performance and
* memory perspective).  In our applications we have millions of small objects and
* wasted memory would become a big problem.
*
* For example a Serialized Boolean takes 47 bytes which means it will fit into the
* 64byte LRU.  Using 1 byte means it will fit into the 8 byte LRU thus saving 8x
* the memory.  This also saves the CPU performance since we don't have to
* serialize bytes back and forth and we can compute the byte[] value directly.
*
* One problem would be when the user calls get() because doing so would require
* the app to know the type of the object stored as a bytearray inside memcached
* (since the user will probably cast).
*
* If we assume the basic types are interned we could use the first byte as the
* type with the remaining bytes as the value.  Then on get() we could read the
* first byte to determine the type and then construct the correct object for it.
* This would prevent the ClassCastException I talked about above.
*
* We could remove the setSerialize() option and just assume that standard VM types
* are always internd in this manner.
*
* mc.set( "foo", new Boolean.TRUE ); Boolean b = (Boolean)mc.get( "foo" );
*
* And the type casts would work because internally we would create a new Boolean
* to return back to the client.
*
* This would reduce memory footprint and allow for a virtual implementation of the
* Externalizable interface which is much faster than Serialzation.
*
* Currently the memory improvements would be:
*
* java.lang.Boolean - 8x performance improvement (now just two bytes)
* java.lang.Integer - 16x performance improvement (now just 5 bytes)
*
* Most of the other primitive types would benefit from this optimization.
* java.lang.Character being another obvious example.
*
* I know it seems like I'm being really picky here but for our application I'd
* save 1G of memory right off the bat.  We'd go down from 1.152G of memory used
* down to 144M of memory used which is much better IMO.
*
* http://java.sun.com/docs/books/tutorial/native1.1/integrating/types.html
*
* @author <a href="mailto:burton@peerfear.org">Kevin A. Burton</a>
* @author Greg Whalin <greg@meetup.com>
*/
public class NativeHandler {

// logger
private static Logger log =
Logger.getLogger( NativeHandler.class.getName() );

/**
* Detemine of object can be natively serialized by this class.
*
* @param value Object to test.
* @return true/false
*/
public static boolean isHandled( Object value ) {

return (
value instanceof Byte            ||
value instanceof Boolean         ||
value instanceof Integer         ||
value instanceof Long            ||
value instanceof Character       ||
value instanceof String          ||
value instanceof StringBuffer    ||
value instanceof Float           ||
value instanceof Short           ||
value instanceof Double          ||
value instanceof Date            ||
value instanceof StringBuilder   ||
value instanceof byte[]
)
? true
: false;
    }

/**
* Returns the flag for marking the type of the byte array.
*
* @param value Object we are storing.
* @return int marker
*/
public static int getMarkerFlag( Object value ) {

if ( value instanceof Byte )
return MemcachedClient.MARKER_BYTE;

if ( value instanceof Boolean )
return MemcachedClient.MARKER_BOOLEAN;

if ( value instanceof Integer )
return MemcachedClient.MARKER_INTEGER;

if ( value instanceof Long )
return MemcachedClient.MARKER_LONG;

if ( value instanceof Character )
return MemcachedClient.MARKER_CHARACTER;

if ( value instanceof String )
return MemcachedClient.MARKER_STRING;

if ( value instanceof StringBuffer )
return MemcachedClient.MARKER_STRINGBUFFER;

if ( value instanceof Float )
return MemcachedClient.MARKER_FLOAT;

if ( value instanceof Short )
return MemcachedClient.MARKER_SHORT;

if ( value instanceof Double )
return MemcachedClient.MARKER_DOUBLE;

if ( value instanceof Date )
return MemcachedClient.MARKER_DATE;

if ( value instanceof StringBuilder )
return MemcachedClient.MARKER_STRINGBUILDER;

if ( value instanceof byte[] )
return MemcachedClient.MARKER_BYTEARR;

return -1;
}

/**
* Encodes supported types
*
* @param value Object to encode.
* @return byte array
*
* @throws Exception If fail to encode.
*/
public static byte[] encode( Object value ) throws Exception {

if ( value instanceof Byte )
return encode( (Byte)value );

if ( value instanceof Boolean )
return encode( (Boolean)value );

if ( value instanceof Integer )
return encode( ((Integer)value).intValue() );

if ( value instanceof Long )
return encode( ((Long)value).longValue() );

if ( value instanceof Character )
return encode( (Character)value );

if ( value instanceof String )
return encode( (String)value );

if ( value instanceof StringBuffer )
return encode( (StringBuffer)value );

if ( value instanceof Float )
return encode( ((Float)value).floatValue() );

if ( value instanceof Short )
return encode( (Short)value );

if ( value instanceof Double )
return encode( ((Double)value).doubleValue() );

if ( value instanceof Date )
return encode( (Date)value);

if ( value instanceof StringBuilder )
return encode( (StringBuilder)value );

if ( value instanceof byte[] )
return encode( (byte[])value );

return null;
}

protected static byte[] encode( Byte value ) {
byte[] b = new byte[1];
b[0] = value.byteValue();
return b;
}

protected static byte[] encode( Boolean value ) {
byte[] b = new byte[1];

if ( value.booleanValue() )
b[0] = 1;
else
b[0] = 0;

return b;
}

protected static byte[] encode( int value ) {
return getBytes( value );
}

protected static byte[] encode( long value ) throws Exception {
return getBytes( value );
}

protected static byte[] encode( Date value ) {
return getBytes( value.getTime() );
}

protected static byte[] encode( Character value ) {
return encode( value.charValue() );
}

protected static byte[] encode( String value ) throws Exception {
return value.getBytes( "UTF-8" );
}

protected static byte[] encode( StringBuffer value ) throws Exception {
return encode( value.toString() );
}

protected static byte[] encode( float value ) throws Exception {
return encode( (int)Float.floatToIntBits( value ) );
}

protected static byte[] encode( Short value ) throws Exception {
return encode( (int)value.shortValue() );
}

protected static byte[] encode( double value ) throws Exception {
return encode( (long)Double.doubleToLongBits( value ) );
}

protected static byte[] encode( StringBuilder value ) throws Exception {
return encode( value.toString() );
}

protected static byte[] encode( byte[] value ) {
return value;
}

protected static byte[] getBytes( long value ) {
byte[] b = new byte[8];
b[0] = (byte)((value >> 56) & 0xFF);
b[1] = (byte)((value >> 48) & 0xFF);
b[2] = (byte)((value >> 40) & 0xFF);
b[3] = (byte)((value >> 32) & 0xFF);
b[4] = (byte)((value >> 24) & 0xFF);
b[5] = (byte)((value >> 16) & 0xFF);
b[6] = (byte)((value >> & 0xFF);
b[7] = (byte)((value >> 0) & 0xFF);
return b;
}

protected static byte[] getBytes( int value ) {
byte[] b = new byte[4];
b[0] = (byte)((value >> 24) & 0xFF);
b[1] = (byte)((value >> 16) & 0xFF);
b[2] = (byte)((value >> & 0xFF);
b[3] = (byte)((value >> 0) & 0xFF);
return b;
}

/**
* Decodes byte array using memcache flag to determine type.
*
* @param b
* @param marker
* @return
* @throws Exception
*/
public static Object decode( byte[] b, int flag ) throws Exception {

if ( b.length < 1 )
return null;


if ( ( flag & MemcachedClient.MARKER_BYTE ) == MemcachedClient.MARKER_BYTE )
return decodeByte( b );

if ( ( flag & MemcachedClient.MARKER_BOOLEAN ) == MemcachedClient.MARKER_BOOLEAN )
return decodeBoolean( b );

if ( ( flag & MemcachedClient.MARKER_INTEGER ) == MemcachedClient.MARKER_INTEGER )
return decodeInteger( b );

if ( ( flag & MemcachedClient.MARKER_LONG ) == MemcachedClient.MARKER_LONG )
return decodeLong( b );

if ( ( flag & MemcachedClient.MARKER_CHARACTER ) == MemcachedClient.MARKER_CHARACTER )
return decodeCharacter( b );

if ( ( flag & MemcachedClient.MARKER_STRING ) == MemcachedClient.MARKER_STRING )
return decodeString( b );

if ( ( flag & MemcachedClient.MARKER_STRINGBUFFER ) == MemcachedClient.MARKER_STRINGBUFFER )
return decodeStringBuffer( b );

if ( ( flag & MemcachedClient.MARKER_FLOAT ) == MemcachedClient.MARKER_FLOAT )
return decodeFloat( b );

if ( ( flag & MemcachedClient.MARKER_SHORT ) == MemcachedClient.MARKER_SHORT )
return decodeShort( b );

if ( ( flag & MemcachedClient.MARKER_DOUBLE ) == MemcachedClient.MARKER_DOUBLE )
return decodeDouble( b );

if ( ( flag & MemcachedClient.MARKER_DATE ) == MemcachedClient.MARKER_DATE )
return decodeDate( b );

if ( ( flag & MemcachedClient.MARKER_STRINGBUILDER ) == MemcachedClient.MARKER_STRINGBUILDER )
return decodeStringBuilder( b );

if ( ( flag & MemcachedClient.MARKER_BYTEARR ) == MemcachedClient.MARKER_BYTEARR )
return decodeByteArr( b );

return null;
}

// decode methods
protected static Byte decodeByte( byte[] b ) {
return new Byte( b[0] );
}

protected static Boolean decodeBoolean( byte[] b ) {
boolean value = b[0] == 1;
return ( value ) ? Boolean.TRUE : Boolean.FALSE;
}

protected static Integer decodeInteger( byte[] b ) {
return new Integer( toInt( b ) );
}

protected static Long decodeLong( byte[] b ) throws Exception {
return new Long( toLong( b ) );
}

protected static Character decodeCharacter( byte[] b ) {
return new Character( (char)decodeInteger( b ).intValue() );
}

protected static String decodeString( byte[] b ) throws Exception {
return new String( b, "UTF-8" );
}

protected static StringBuffer decodeStringBuffer( byte[] b ) throws Exception {
return new StringBuffer( decodeString( b ) );
}

protected static Float decodeFloat( byte[] b ) throws Exception {
Integer l = decodeInteger( b );
return new Float( Float.intBitsToFloat( l.intValue() ) );
}

protected static Short decodeShort( byte[] b ) throws Exception {
return new Short( (short)decodeInteger( b ).intValue() );
}

protected static Double decodeDouble( byte[] b ) throws Exception {
Long l = decodeLong( b );
return new Double( Double.longBitsToDouble( l.longValue() ) );
}

protected static Date decodeDate( byte[] b ) {
return new Date( toLong( b ) );
}

protected static StringBuilder decodeStringBuilder( byte[] b ) throws Exception {
return new StringBuilder( decodeString( b ) );
}

protected static byte[] decodeByteArr( byte[] b ) {
return b;
}

/**
* This works by taking each of the bit patterns and converting them to
* ints taking into account 2s complement and then adding them..
*
* @param b
* @return
*/
protected static int toInt( byte[] b ) {
return (((((int) b[3]) & 0xFF) << 32) +
((((int) b[2]) & 0xFF) << 40) +
((((int) b[1]) & 0xFF) << 48) +
((((int) b[0]) & 0xFF) << 56));
}   

protected static long toLong( byte[] b ) {
return ((((long) b[7]) & 0xFF) +
((((long) b[6]) & 0xFF) << +
((((long) b[5]) & 0xFF) << 16) +
((((long) b[4]) & 0xFF) << 24) +
((((long) b[3]) & 0xFF) << 32) +
((((long) b[2]) & 0xFF) << 40) +
((((long) b[1]) & 0xFF) << 48) +
((((long) b[0]) & 0xFF) << 56));
}   
}
分享到:
评论

相关推荐

    android NDK实现的Hanlder-消息队列-native多线程实例

    1. Native Handler接口:定义原生的Handler类,包含发送消息和处理消息的方法。 2. Message结构体:用于存储消息信息,包括消息类型、参数和目标Handler指针。 3. MessageQueue类:实现消息队列的数据结构和操作方法...

    安卓逆向学习笔记之安卓APP加壳技术分类与初识VMP.docx

    `nativeHandler`会解析调用栈,确定实际要执行的是`funcA()`,并执行相应的opcode。 #### VMP的应用案例 在实际应用中,VMP不仅可以应用于具体的函数,还可以应用于整个应用程序的启动过程。例如,在Application类...

    jsdemo_iOS原生h5交互_源码

    window.webkit.messageHandlers.nativeHandler.postMessage("Hello Native!"); ``` - **实现WKScriptMessageHandler协议**: 在原生代码中处理JavaScript的回调。 ```swift func userContentController(_ ...

    WKWebViewJSBridge

    - **Native Handler**:这部分是Objective-C或Swift代码,负责注册原生方法供JavaScript调用,以及接收和处理JavaScript的回调。 - **JavaScript Core**:在JavaScript端,有一个桥接对象,用于调用注册在Native ...

    java调用memcached

    `NativeHandler`可能是一个处理网络I/O的类,它使用Java的原生接口(JNI)来实现更高效的网络通信。通过JNI,可以直接调用C/C++编写的底层库,以获得比纯Java更优秀的性能。 `ByteBufArrayInputStream`看起来是一个...

    iosH5ForApp

    JSBridge通常包括两个部分:在App端定义的Native Handler和在H5端定义的JavaScript接口。 4. **注入JavaScript代码**: 通过`WKWebView`的`evaluateJavaScript:`方法,可以在加载H5页面后动态注入JavaScript代码,...

    HelpetWebViewJavascriptBridge

    1. **注册原生处理程序(Register Native Handler)**:在Objective-C代码中,你可以注册一个方法作为JavaScript的回调。例如,当JavaScript执行特定的函数时,`HelpetWebViewJavascriptBridge`会调用这个预先注册的...

    react-native-gesture-handler:声明性API将平台本机触摸和手势系统暴露给React Native

    React Native Gesture Handler提供了本机驱动的手势管理API,用于在React Native中构建最佳的基于触摸的体验。 使用此库,手势不再由JS响应器系统控制,而是在UI线程中被识别和跟踪。 它使触摸交互和手势跟踪不仅...

    Handler机制及原理探究.pdf

    Handler使用简单功能强大,常被用作线程间传递消息的组件,而且还可以用于跨进程。 消息机制背后有包括Looper ,MessageQueue管理和分发消息的实现,同时在Native层也单独实现了一套类 似的机制,接收和处理Native...

    react-native-exception-handler:一个react native模块,可让您注册一个全局错误处理程序,以捕获致命非致命未捕获的异常

    React Native模块,使您可以注册一个全局错误处理程序,该错误处理程序可以捕获致命/非致命未捕获异常。 该模块有助于防止RN Apps突然崩溃,而不会向用户显示优美的消息。 在当前情况下: In DEV mode , you get ...

    react-native-exception-handler-example:一个示例仓库显示了如何集成react-native-exception-handler

    git clone https://github.com/master-atul/react-native-exception-handler-example yarn install react-native run-ios --configuration Release或react-native run-android --variant=release 即使在开发模式...

    Handler对象中使用匿名内部类或非静态内部类正确地释放消息避免内存泄漏或增加Native内存

    然而,不当使用Handler,尤其是结合匿名内部类或非静态内部类,可能导致内存泄漏和Native内存增加,这对应用性能和稳定性造成负面影响。 首先,我们要理解内存泄漏的概念。内存泄漏是指程序中已分配的内存没有被...

    react native 实现app demo

    然后,你需要安装`react-navigation`库及其依赖,如`react-native-gesture-handler`和`react-native-reanimated`: ```bash cd MyApp npm install @react-navigation/native npm install react-native-gesture-...

    ReactNative自定义cell的滑动删除

    在iOS中,这个功能通常通过UITableView的滑动手势来实现,而在React Native中,我们可以使用`react-native-swipeout`或`react-native-gesture-handler`库来模拟类似的功能。 1. **使用`react-native-swipeout`**: ...

    react-native的demo

    通过查看这个文件,我们可以了解项目所依赖的具体版本和任何额外的工具或库,比如`react-native-gesture-handler`或`react-native-reanimated`等。 `.gitignore`文件定义了在Git版本控制中应当忽略的文件类型。对于...

    reactnative异常处理库

    以`master-atul-react-native-exception-handler-d88d14a`为例,这可能是某个React Native异常处理库的源码仓库的一个特定版本。这个库可能包含了错误处理的实现,包括错误的捕获、记录、上报和恢复机制,开发者可以...

    react-native TabBar和Nav

    1. 安装`react-navigation`库:在项目中运行`npm install @react-navigation/native`和`npm install react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @...

    react-native之RNGestureHandlerModule.State

    这主要是因为React Native应用未能正确加载或配置`react-native-gesture-handler`库导致的。具体来说: 1. **库未安装**:项目中未安装`react-native-gesture-handler`库。 2. **链接问题**:即使已经安装了`react-...

    一个ReactNative登录动画的例子

    6. **第三方库**:React Native社区提供了许多第三方库,例如`react-native-reanimated`和`react-native-gesture-handler`,它们可以增强 Animated 库的功能,实现更复杂的交互和动画。 7. **错误处理和调试**:在...

    React-Native 实现点击Tab标签切换Tab页面

    npm install react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view # 或者使用yarn yarn add @react-navigation/...

Global site tag (gtag.js) - Google Analytics