序列化:把数据结构或者对象转换成二进制串的过程。
反序列化:把二进制串转换成数据结构或者对象的过程。
二进制串:序列化所生成的二进制串指的是存储在内存中的一块数据。二进制串在Java里面所指的是byte[]。
应用场景:数据库,XML等文件存储,套接字,RMI
序列化的作用:
序列化和反序列化的过程是为了方便以本地文件、数据库、网络流、RMI等方式传输数据。
如果没有序列化的存在,例如:要利用XML等文件存储对象中的数据时,我们就需要手动把对象中的数据逐个存入文件中。传输完成后再从文件中逐个取出数据在转换成对象。(序列化反序列化其实就是这个过程,只是把该功能封装起来了)
在操作数据库时,有时候我们并不会实现序列化也可以保存到数据库中,如:
public class Car{
private int price;
private String color;
public static String model;
transient String user;
}
数据库中保存了对应的表字段,插入数据库的时候,只需要把car对象的变量值保存到相应的表字段就可以了。
这是否说明了数据库的场景下不需要序列化?
查看资料后,比较好的解释是:Sql中的数据结构恰好能对应java的基础数据类型,因此不用序列化也可以直接保存。另外一种数据库Nosql是没有定义数据结构的,因此在保存到此类数据库时,还是需要实现序列化的。(硬盘也是没有相应的数据结构的)
序列化的实现:
- java提供了Serializable接口
- android提供了Parcelable接口
Serializable接口
Serializable接口没有定义任何方法或字段,仅用于识别可序列化的语义。
java集合多数实现了Serializable接口,比如ArrayList,HashSet,HashMap等等。
Serializable的使用注意事项:
- 实现Serializable需要使用IO流对文件进行读写操作
- static 修饰的变量不参与序列化
- transient 修饰的变量也不参与序列化,反序列化后该变量变为默认值
- 序列化过程中,如果在Serializable实现类中,使用了非Serializable实现类的对象,则该对象在反序列化时,里面所有的变量均变为默认值(不参与序列化)
- 子类实现了Serializable,而父类没有实现Serializable。父类必须要有无参构造函数。
- Serializable的实现类均有一个private static final long serialVersionUID
变量,如果没有显示定义,在序列化的时候jvm会给我们默认定义,默认定义的serialVersionUID
会跟随实现类实体的修改而动态变化,这个需要注意。这个serialVersionUID
是用来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体类的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常,即InvalidCastException。如果需要自定义serialVersionUID
,可以参照ObjectStreamClass.java,这个源码中有对serialVersionUID
进行自定义。另外,我们可以通过ObjectStreamClass类来获取serialVersionUID 。参见例子。
序列化到文件存储中的例子:
public class Car extends ProductionBase implements Serializable{
private int price;
private String color;
static String model = "Lamborghini";
transient String user;
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
@Override
public String toString() {
return "Car{" +
"price=" + price +
", color='" + color + '\'' +
", model='" + model + '\'' +
", user='" + user + '\'' +
", " + super.toString() + '\'' +
'}';
}
}
public class ProductionBase {
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "ProductionBase{" +
"address='" + address + '\'' +
'}';
}
}
public class SerializableTest {
private static String path = "F:\\AndroidStudioProjects\\Android_Example\\java_example\\src\\main\\java\\com\\example\\serializable\\SerializableCar.txt";
public static void main(String args[]){
Car myCar = new Car();
myCar.setColor("while");
myCar.setPrice(9999999);
myCar.setUser("my wife");
myCar.setAddress("China");
try {
System.out.println("myCar is :" + myCar.toString());
SerializableCar(myCar);//序列化
Car.model = "Ferrari";
myCar.setColor("black");
myCar.setPrice(8888888);
myCar.setUser("myself");
myCar.setAddress("Japan");
Object object = DeserializationCar(path);//反序列化
Car newCar = (Car)object;
System.out.println("newCar is :" + newCar.toString());
//获取默认的SerialVersionUID值
ObjectStreamClass osc2 = ObjectStreamClass.lookup(Car.class);
System.out.println("SerialVersionUID :" + osc2.getSerialVersionUID());
}catch (Exception e){
e.printStackTrace();
}
}
//序列化
public static void SerializableCar(Object object) throws IOException {
File mFile = new File(path);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(mFile));
oos.writeObject(object);
oos.close();
System.out.println("SerializableCar is success, Serializable file is in "+ path);
}
//反序列化
public static Object DeserializationCar(String mPath) throws IOException,ClassNotFoundException{
File mFile = new File(mPath);
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(mFile));
Object object = ois.readObject();
System.out.println("DeserializationCar is success, return the Object");
return object;
}
}
打印输出:
myCar is :Car{price=9999999, color='while', model='Lamborghini', user='my wife', ProductionBase{address='China'}'}
SerializableCar is success, Serializable file is in F:\AndroidStudioProjects\Android_Example\java_example\src\main\java\com\example\serializable\SerializableCar.txt
DeserializationCar is success, return the Object
newCar is :Car{price=9999999, color='while', model='Ferrari', user='null', ProductionBase{address='null'}'}
SerialVersionUID :5568593075854263741
以上的例子中,在执行序列化之后再修改对象的值,通过查看log打印的差异之处,可以看到变量是否被序列化。
Parcelable接口
鉴于移动设备的内存资源比较稀缺,Android设计了Parcelable序列化的方式,Parcelable和Serializable之间的差别有:
Serializable序列化
- 通过本地文件、数据库、网络流、RMI等方式进行数据的传输。
- 使用外部存储器进行数据的读写操作,效率低。
- 除了transient和static修饰的变量,类中所有的变量都会实现序列化。
- 使用起来比较简单。
Parcelable序列化
- 一般只能以内存的方式进行数据的传输。
- 直接在内存中对数据进行读写,效率高。
- 可以自定义需要序列化的变量,自定义反序列化的变量。
- 使用起来比较繁琐。
一. Parcelable的使用
在Parcelable接口的注释中,官方已经规定好该怎么样去使用Parcelable了,如下:
* <pre>
* public class MyParcelable implements Parcelable {
* private int mData;
*
* public int describeContents() {
* return 0;
* }
*
* public void writeToParcel(Parcel out, int flags) {
* out.writeInt(mData);
* }
*
* public static final Parcelable.Creator<MyParcelable> CREATOR
* = new Parcelable.Creator<MyParcelable>() {
* public MyParcelable createFromParcel(Parcel in) {
* return new MyParcelable(in);
* }
*
* public MyParcelable[] newArray(int size) {
* return new MyParcelable[size];
* }
* };
*
* private MyParcelable(Parcel in) {
* mData = in.readInt();
* }
* }</pre>
总结起来有四点:
1. 必须实现writeToParcel()方法,把数据封装到Parcel中,Parcel帮我们实现了序列化功能(类似于Serializable输出流)
2. 必须实现一个public static final类型的CREATOR变量,并实现createFromParcel()方法和newArray()方法。既然Parcel帮我们实现了序列化的功能,那么它也帮我们实现了反序列化的功能,我们需要从createFromParcel()方法中获取Parcel对象以获取反序列化后的数据。
3. 从Parcel中获取反序列化后的数据。这一步可以在Parcelable子类的构造方法中执行也可以在createFromParcel()中执行。
4. 实现describeContents()方法,这个方法默认返回0。暂不知具体作用。
实现了Parcelable之后,就可以正常使用Parcelable进行序列化反序列化的操作了。但是它并不像Serializable的使用方式一样,需要自己直接调用writeToParcel()和createFromParcel()去实现,这些调用全部被封装起来了,Parcelable一般是建议使用在Intent意图跳转的时候传输数据,比如:
xxxx
Intent mIntent = new Intent(getApplicationContext(), xxxx.class);
Bundle mBundle = new Bundle();
mBundle.putParcelable("xxxx", Parcelable实现类对象);
mIntent.putExtras(mBundle);
startActivity(mIntent);
xxxxx
Intent mIntent = getIntent();
Parcelable xx= mIntent.getParcelableExtra("xxxx");
具体的例子如下:
public class Car extends ProductionBase implements Parcelable {
public int price;
public String color;
public static String model;
public transient String user;
public Car(Parcel in){
price = in.readInt();
color = in.readString();
model = in.readString();
user = in.readString();
}
public static final Creator<Car> CREATOR = new Creator<Car>(){
@Override
public Car[] newArray(int size) {
return new Car[size];
}
@Override
public Car createFromParcel(Parcel source) {
Log.d("MainActivity", "createFromParcel :" + source.toString()+ Log.getStackTraceString(new Throwable()));
return new Car(source);
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(price);
dest.writeString(color);
dest.writeString(model);
dest.writeString(user);
Log.d("MainActivity", "writeToParcel:" + source.toString()+ Log.getStackTraceString(new Throwable()));
}
}
public class ProductionBase {
private String address;
}
public class MainActivity extends AppCompatActivity {
public static String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Parcel mParcel = Parcel.obtain();
final Car mCar = new Car(mParcel);
Car.model = "Lamborghini";
mCar.setColor("while");
mCar.setPrice(9999999);
mCar.setUser("my wife");
mCar.setAddress("China");
Log.d(TAG, "new Car :" + mCar.toString());
Button button = (Button)findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent mIntent = new Intent(getApplicationContext(), Main2Activity.class);
Bundle mBundle = new Bundle();
mBundle.putParcelable("mydata", mCar);
mIntent.putExtras(mBundle);
Log.d(TAG, "OnClickListener :" + mIntent.getExtras().getParcelable("mydata").toString());
startActivity(mIntent);
}
});
}
}
public class Main2Activity extends AppCompatActivity {
private String TAG = "Main2Activity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
try {
Intent mIntent = getIntent();
Car mCar = mIntent.getParcelableExtra("mydata");
Log.d(TAG, "get Car from intent :" + mCar.toString());
}catch (Exception e){
e.printStackTrace();
}
}
}
二. writeToParcel()和createFromParcel()源码分析
以上的例子中,并没有看到writeToParcel()和createFromParcel()被显示的调用。其实那只是被封装起来了而已。如下:
首先,Intent和Bundle都是Parcelable的实现类,如果我们把Parcelable 实现类对象再保存到Intent和Bundle中,就相当于是Parcelable 的嵌套使用了。
Intent内部维护了一个Bundle对象,用来保存所有Intent中的数据。Intent中取出数据也是来自Bundle。而Bundle内部则是使用了Map键值对的形式来保存数据。
Intent.java
public Intent putExtra(String name, Parcelable value) {
if (mExtras == null) {
mExtras = new Bundle();
}
mExtras.putParcelable(name, value);
return this;
}
public <T extends Parcelable> T getParcelableExtra(String name) {
return mExtras == null ? null : mExtras.<T>getParcelable(name);
}
Bundle.java
ArrayMap<String, Object> mMap = null;
public void putParcelable(@Nullable String key, @Nullable Parcelable value) {
unparcel();
mMap.put(key, value);
mFdsKnown = false;
}
public <T extends Parcelable> T getParcelable(@Nullable String key) {
unparcel();
Object o = mMap.get(key);
if (o == null) {
return null;
}
try {
return (T) o;
} catch (ClassCastException e) {
typeWarning(key, o, "Parcelable", e);
return null;
}
}
例子中,我们在writeToParcel()和createFromParcel()方法中打印了调用栈:
writeToParcel():
createFromParcel():
根据调用栈的流程,我们从ActivityManagerProxy.java的startActivity()开始研究源码:
ActivityManagerProxy.java
public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
data.writeString(callingPackage);
//获取Parcel对象,把Intent中的信息保存到Parcel对象中。之后就是Parcel实现序列化的过程。
intent.writeToParcel(data, 0);
data.writeString(resolvedType);
data.writeStrongBinder(resultTo);
data.writeString(resultWho);
data.writeInt(requestCode);
data.writeInt(startFlags);
if (profilerInfo != null) {
data.writeInt(1);
profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
} else {
data.writeInt(0);
}
if (options != null) {
data.writeInt(1);
options.writeToParcel(data, 0);
} else {
data.writeInt(0);
}
//Intent意图跳转,无论是否是跨进程通讯,都执行此方法。
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
reply.readException();
int result = reply.readInt();
reply.recycle();//序列化反序列化结束后,需要释放Parcel对象通过JNI调用C++代码申请的内存空间
data.recycle();
return result;
}
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
switch (code) {
case START_ACTIVITY_TRANSACTION:
{
data.enforceInterface(IActivityManager.descriptor);
IBinder b = data.readStrongBinder();
IApplicationThread app = ApplicationThreadNative.asInterface(b);
String callingPackage = data.readString();
Intent intent = Intent.CREATOR.createFromParcel(data);//反序列化获取Intent信息。(new Intent)
String resolvedType = data.readString();
IBinder resultTo = data.readStrongBinder();
String resultWho = data.readString();
int requestCode = data.readInt();
int startFlags = data.readInt();
ProfilerInfo profilerInfo = data.readInt() != 0
? ProfilerInfo.CREATOR.createFromParcel(data) : null;
//如果startActivity()时传入了Bundle参数,反序列化获取Bundle信息(new Bundle)
Bundle options = data.readInt() != 0
? Bundle.CREATOR.createFromParcel(data) : null;
//调用了AMS中的startActivity(),根据反序列得到的Intent信息,启动Activity
int result = startActivity(app, callingPackage, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profilerInfo, options);
reply.writeNoException();
reply.writeInt(result);
return true;
}
......
}
Intent.java
//把Intent中的Bundle对象引用传递到Parcel对象中
public void writeToParcel(Parcel out, int flags) {
out.writeString(mAction);
Uri.writeToParcel(out, mData);
out.writeString(mType);
out.writeInt(mFlags);
out.writeString(mPackage);
ComponentName.writeToParcel(mComponent, out);
if (mSourceBounds != null) {
out.writeInt(1);
mSourceBounds.writeToParcel(out, flags);
} else {
out.writeInt(0);
}
if (mCategories != null) {
final int N = mCategories.size();
out.writeInt(N);
for (int i=0; i<N; i++) {
out.writeString(mCategories.valueAt(i));
}
} else {
out.writeInt(0);
}
if (mSelector != null) {
out.writeInt(1);
mSelector.writeToParcel(out, flags);
} else {
out.writeInt(0);
}
if (mClipData != null) {
out.writeInt(1);
mClipData.writeToParcel(out, flags);
} else {
out.writeInt(0);
}
out.writeInt(mContentUserHint);
out.writeBundle(mExtras);//把Intent中的Bundle对象引用传递到Parcel对象中
}
Parcel.java
public final void writeBundle(Bundle val) {
if (val == null) {
writeInt(-1);
return;
}
val.writeToParcel(this, 0);
}
//循环ArrayMap集合,把集合中的数据通过Parcel写入到内存
/* package */ void writeArrayMapInternal(ArrayMap<String, Object> val) {
if (val == null) {
writeInt(-1);
return;
}
final int N = val.size();
writeInt(N);
if (DEBUG_ARRAY_MAP) {
RuntimeException here = new RuntimeException("here");
here.fillInStackTrace();
Log.d(TAG, "Writing " + N + " ArrayMap entries", here);
}
int startPos;
for (int i=0; i<N; i++) { //循环map集合,把map中的数据写入到内存
if (DEBUG_ARRAY_MAP) startPos = dataPosition();
writeString(val.keyAt(i));
writeValue(val.valueAt(i));
if (DEBUG_ARRAY_MAP) Log.d(TAG, " Write #" + i + " "
+ (dataPosition()-startPos) + " bytes: key=0x"
+ Integer.toHexString(val.keyAt(i) != null ? val.keyAt(i).hashCode() : 0)
+ " " + val.keyAt(i));
}
}
//根据键值对中value的类型匹配对应的处理方法
public final void writeValue(Object v) {
if (v == null) {
writeInt(VAL_NULL);
} else if (v instanceof String) {
writeInt(VAL_STRING);
writeString((String) v);
} else if (v instanceof Integer) {
writeInt(VAL_INTEGER);
writeInt((Integer) v);
} else if (v instanceof Map) {
writeInt(VAL_MAP);
writeMap((Map) v);
} else if (v instanceof Bundle) {
// Must be before Parcelable
writeInt(VAL_BUNDLE);
writeBundle((Bundle) v);
} else if (v instanceof Parcelable) {
writeInt(VAL_PARCELABLE);
writeParcelable((Parcelable) v, 0);
}
......
}
//调用Parcelable实现类中的writeToParcel()方法,把数据写入内存
public final void writeParcelable(Parcelable p, int parcelableFlags) {
if (p == null) {
writeString(null);
return;
}
writeParcelableCreator(p);
p.writeToParcel(this, parcelableFlags);
}
//在数据写入内存之前,把Parcelable实现类的类名也写入到内存
public final void writeParcelableCreator(Parcelable p) {
String name = p.getClass().getName();
writeString(name);
}
//Parcel读取内存数据,然后把数据保存到一个新的ArrayMap集合中
/* package */ void readArrayMapInternal(ArrayMap outVal, int N,
ClassLoader loader) {
if (DEBUG_ARRAY_MAP) {
RuntimeException here = new RuntimeException("here");
here.fillInStackTrace();
Log.d(TAG, "Reading " + N + " ArrayMap entries", here);
}
int startPos;
while (N > 0) {
if (DEBUG_ARRAY_MAP) startPos = dataPosition();
String key = readString();
Object value = readValue(loader);//读取内存数据
if (DEBUG_ARRAY_MAP) Log.d(TAG, " Read #" + (N-1) + " "
+ (dataPosition()-startPos) + " bytes: key=0x"
+ Integer.toHexString((key != null ? key.hashCode() : 0)) + " " + key);
outVal.append(key, value);
N--;
}
outVal.validate();
}
//调用Parcelable实现类中的匿名内部类Creator中的createFromParcel()方法
public final <T extends Parcelable> T readParcelable(ClassLoader loader) {
Parcelable.Creator<?> creator = readParcelableCreator(loader);
if (creator == null) {
return null;
}
if (creator instanceof Parcelable.ClassLoaderCreator<?>) {
Parcelable.ClassLoaderCreator<?> classLoaderCreator =
(Parcelable.ClassLoaderCreator<?>) creator;
return (T) classLoaderCreator.createFromParcel(this, loader);
}
return (T) creator.createFromParcel(this);
}
Bundle.java & BaseBundle.java
//调用父类的writeToParcelInner()方法处理Parcel
public void writeToParcel(Parcel parcel, int flags) {
final boolean oldAllowFds = parcel.pushAllowFds(mAllowFds);
try {
super.writeToParcelInner(parcel, flags);
} finally {
parcel.restoreAllowFds(oldAllowFds);
}
}
//把Bundle中的map集合中的数据通过parcel对象写入内存,并设置parcel对象的相关参数。
void writeToParcelInner(Parcel parcel, int flags) {
if (mParcelledData != null) {
if (mParcelledData == EMPTY_PARCEL) {
parcel.writeInt(0);
} else {
int length = mParcelledData.dataSize();
parcel.writeInt(length);
parcel.writeInt(BUNDLE_MAGIC);
parcel.appendFrom(mParcelledData, 0, length);
}
} else {
// Special case for empty bundles.
if (mMap == null || mMap.size() <= 0) {
parcel.writeInt(0);
return;
}
int lengthPos = parcel.dataPosition();
parcel.writeInt(-1); // dummy, will hold length
parcel.writeInt(BUNDLE_MAGIC);
int startPos = parcel.dataPosition();
parcel.writeArrayMapInternal(mMap);//把Bundle中的map对象保存到parcel对象中
int endPos = parcel.dataPosition();
// Backpatch length
parcel.setDataPosition(lengthPos);
int length = endPos - startPos;
parcel.writeInt(length);
parcel.setDataPosition(endPos);
}
}
//通过parcel读取内存数据,并把这些数据保存到bundle的map集合中
/* package */ synchronized void unparcel() {
if (mParcelledData == null) {
if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
+ ": no parcelled data");
return;
}
if (mParcelledData == EMPTY_PARCEL) {
if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
+ ": empty");
if (mMap == null) {
mMap = new ArrayMap<String, Object>(1);
} else {
mMap.erase();
}
mParcelledData = null;
return;
}
int N = mParcelledData.readInt();
if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
+ ": reading " + N + " maps");
if (N < 0) {
return;
}
if (mMap == null) {
mMap = new ArrayMap<String, Object>(N);
} else {
mMap.erase();
mMap.ensureCapacity(N);
}
mParcelledData.readArrayMapInternal(mMap, N, mClassLoader);
mParcelledData.recycle();
mParcelledData = null;
if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
+ " final map: " + mMap);
}
总结以上源码:
- 执行putExtra()把Parcelable对象加入到Intent中,实际上就是创建了Bundle对象,把Parcelable对象保存到了Bundle对象的map集合中。执行startActivity()的过程中,ActivityManagerProxy会获取一个Parcel对象,并把Intent中携带的Bundle对象引用传递给Parcel对象,Parcel通过Bundle对象的引用访问map集合,把map集合中的Parcelable类型的数据写入内存。序列化结束。(Intent也是Parcelable类型,它同样序列化了)
- 在startActivity()中,序列化结束后,接着执行onTransact()方法,马上借助Parcel对象反序列化了Intent和Bundle。AMS根据Intent信息启动了Activity,接着释放了Parcel对象所占有的内存空间(C++)。
- 当我们调用getIntent().getParcelableExtra(String key)时,会先调用Bundle中的unparcel()方法通过Parcel对象读取内存中的数据,然后保存到Bundle的Map集合(空集合)中,之后通过key返回map中的value值。反序列化结束。
三. Parcel源码分析
Parcelable的序列化和反序列化功能,都封装在了Parcel中,那么Parcel是如何实现在内存中进行序列化和反序列化呢?我们先来看看Parcel中代码的部分实现:
- Parcel 内部维护了两个6位的数组sOwnedPool ,sHolderPool 当做缓冲池。sOwnedPool 中保存的是nativePtr = 0的Parcel 对象。sHolderPool 中保存的是nativePtr != 0的Parcel 对象。由于Parcel 的构造函数是private,因此提供了两个obtain()方法,一个不带参数,一个带int参数(nativePtr 值)。
- nativePtr值是什么,通过JNI的调用关系查看c++代码,发现nativePtr 其实就是一个内存地址的Long类型表示。c代码中把指向内存的指针转换成Long类型的数值。
- Parcel 中对数据的序列化和反序列化是通过JNI调用c++代码来实现的。c代码中的指针可以直接操作内存。
Parcel:
private static final Parcel[] sOwnedPool = new Parcel[POOL_SIZE];
private static final Parcel[] sHolderPool = new Parcel[POOL_SIZE];
private static final int POOL_SIZE = 6;
//获取sOwnedPool 缓冲池中的Parcel对象
public static Parcel obtain() {
final Parcel[] pool = sOwnedPool;
synchronized (pool) {
Parcel p;
for (int i=0; i<POOL_SIZE; i++) {
p = pool[i];
if (p != null) {
pool[i] = null;
if (DEBUG_RECYCLE) {
p.mStack = new RuntimeException();
}
return p;
}
}
}
return new Parcel(0);
}
/*获取sHolderPool缓冲池中的Parcel对象。由于obtain()是protected修饰的且Parcel类定义为final,
*所以此方法只能被子类方法调用,但是Parcel并没有子类。
*/
static protected final Parcel obtain(long obj) {
final Parcel[] pool = sHolderPool;
synchronized (pool) {
Parcel p;
for (int i=0; i<POOL_SIZE; i++) {
p = pool[i];
if (p != null) {
pool[i] = null;
if (DEBUG_RECYCLE) {
p.mStack = new RuntimeException();
}
p.init(obj);
return p;
}
}
}
return new Parcel(obj);
}
private Parcel(long nativePtr) {
if (DEBUG_RECYCLE) {
mStack = new RuntimeException();
}
//Log.i(TAG, "Initializing obj=0x" + Integer.toHexString(obj), mStack);
init(nativePtr);
}
/*如果指定了nativePtr,说明此Parcel对象中的数据已经写入过内存,并且没有被释放掉,
*把nativePtr赋值给*mNativePtr,并把mOwnsNativeParcelObject设置为false(此Parcel对象
*在缓冲池未满的情况下会加入到sHolderPool缓冲池)。如果没有指定nativePtr,说明此
*Parcel对象中的数据没有写入过内存,通过JNI调用与nativeCreate()相映射的方法。把数据
*写入到内存中并返回此数据在内存中的地址赋值给mNativePtr(Long类型),mOwnsNativeParcelObject
*设置为true,此Parcel对象在缓冲池未满的情况下会加入到sOwnedPool缓冲池)
*/
private void init(long nativePtr) {
if (nativePtr != 0) {
mNativePtr = nativePtr;
mOwnsNativeParcelObject = false;
} else {
mNativePtr = nativeCreate();
mOwnsNativeParcelObject = true;
}
}
/*如果当前Parcel对象不再被使用,此方法执行。会调用freeBuffer()释放掉当前Parcel对象
*所指向的mNativePtr数值的内存,并根据mOwnsNativeParcelObject值判断当前Parcel对象
*是保存到sOwnedPool缓冲池中还是sHolderPool缓冲池中。如果缓冲池已满,则不再加入。
*/
public final void recycle() {
if (DEBUG_RECYCLE) mStack = null;
freeBuffer();
final Parcel[] pool;
if (mOwnsNativeParcelObject) {
pool = sOwnedPool;
} else {
mNativePtr = 0;
pool = sHolderPool;
}
synchronized (pool) {
for (int i=0; i<POOL_SIZE; i++) {
if (pool[i] == null) {
pool[i] = this;
return;
}
}
}
}
//通过JNI调用c++代码中与nativeFreeBuffer()相映射的方法,释放内存
private void freeBuffer() {
if (mOwnsNativeParcelObject) {
nativeFreeBuffer(mNativePtr);
}
}
//通过JNI调用c++代码与nativeReadInt()相映射的方法,读取内存中的数据
public final int readInt() {
return nativeReadInt(mNativePtr);
}
//通过JNI调用c++代码与nativeReadString()相映射的方法,读取内存中的数据
public final String readString() {
return nativeReadString(mNativePtr);
}
public final void writeString(String val) {
mReadWriteHelper.writeString(this, val);
}
//通过JNI调用c++代码与writeString()相映射的方法,把数据写入内存
public void writeString(Parcel p, String s) {
nativeWriteString(p.mNativePtr, s);
}
Frameworks/base/core/jni/android_os_Parcel.cpp
这里面有一个函数映射表,映射了java中的方法和c中的方法:
{"nativeCreate", "()J", (void*)android_os_Parcel_create},
{"nativeReadString", "(J)Ljava/lang/String;", (void*)android_os_Parcel_readString},
{"nativeWriteString", "(JLjava/lang/String;)V", (void*)android_os_Parcel_writeString},
{"nativeFreeBuffer", "(J)J", (void*)android_os_Parcel_freeBuffer},
{"nativeReadInt", "(J)I", (void*)android_os_Parcel_readInt},
//c++代码中也定义了相关的Parcel类,新建一个Parcel对象,并把此对象的指针转换成Long类型并返回。
static jlong android_os_Parcel_create(JNIEnv* env, jclass clazz)
{
//Frameworks/native/libs/binder/include/binder/Parcel.h
//Frameworks/native/libs/binder/Parcel.cpp
Parcel* parcel = new Parcel();
return reinterpret_cast<jlong>(parcel);
}
//释放相关Parcel对象指针所指向的内存空间
static jlong android_os_Parcel_freeBuffer(JNIEnv* env, jclass clazz, jlong nativePtr)
{
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
if (parcel != NULL) {
parcel->freeData();
return parcel->getOpenAshmemSize();
}
return 0;
}
//读取Parcel对象指针所指向的内存数据
static jint android_os_Parcel_readInt(jlong nativePtr)
{
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
if (parcel != NULL) {
return parcel->readInt32();
}
return 0;
}
//读取Parcel对象指针所指向的内存数据
static jstring android_os_Parcel_readString(JNIEnv* env, jclass clazz, jlong nativePtr)
{
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
if (parcel != NULL) {
size_t len;
const char16_t* str = parcel->readString16Inplace(&len);
if (str) {
return env->NewString(reinterpret_cast<const jchar*>(str), len);
}
return NULL;
}
return NULL;
}
//在Parcel对象指针所指向的内存中写入数据
static void android_os_Parcel_writeString(JNIEnv* env, jclass clazz, jlong nativePtr, jstring val)
{
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
if (parcel != NULL) {
status_t err = NO_MEMORY;
if (val) {
const jchar* str = env->GetStringCritical(val, 0);
if (str) {
err = parcel->writeString16(
reinterpret_cast<const char16_t*>(str),
env->GetStringLength(val));
env->ReleaseStringCritical(val, str);
}
} else {
err = parcel->writeString16(NULL, 0);
}
if (err != NO_ERROR) {
signalExceptionForError(env, clazz, err);
}
}
}
Frameworks/native/libs/binder/Parcel.cpp
status_t Parcel::writeString16(const String16& str)
{
return writeString16(str.string(), str.size());
}
status_t Parcel::writeString16(const char16_t* str, size_t len)
{
if (str == NULL) return writeInt32(-1);
status_t err = writeInt32(len);
if (err == NO_ERROR) {
len *= sizeof(char16_t);
uint8_t* data = (uint8_t*)writeInplace(len+sizeof(char16_t));
if (data) {
memcpy(data, str, len); //内存操作
*reinterpret_cast<char16_t*>(data+len) = 0;
return NO_ERROR;
}
err = mError;
}
return err;
}
总结以上源码:
java层从Parcel缓冲池中获取Parcel对象,如果Parcel对象的mNativePtr = 0,JNI映射C++代码,也创建C++中的Parcel对象,并为C++中的Parcel对象分配内存空间,把Parcel对象的指针返回给java层的Parcel对象中的mNativePtr。java层的Parcel对象执行writer操作,JNI映射到C++代码,C++层的Parcel对象操作指针对内存进行writer操作。read操作和freeBuffer操作同理。
附:
BaseBundle.java中mParcelledData变量的赋值:
Intent携带Bundle对象进行意图跳转时开始,保存的是ActivityManagerProxy获取的Parcel对象:
startActivity() -> onTransact() -> Intent.CREATOR.createFromParcel(data) ->new Intent(in) ->readFromParcel(in) ->in.readBundle() ->new Bundle(this, length) ->super(parcelledData, length) ->readFromParcelInner(parcelledData, length)
private void readFromParcelInner(Parcel parcel, int length) {
if (length == 0) {
// Empty Bundle or end of data.
mParcelledData = EMPTY_PARCEL;
return;
}
int magic = parcel.readInt();
if (magic != BUNDLE_MAGIC) {
//noinspection ThrowableInstanceNeverThrown
throw new IllegalStateException("Bad magic number for Bundle: 0x"
+ Integer.toHexString(magic));
}
// Advance within this Parcel
int offset = parcel.dataPosition();
parcel.setDataPosition(offset + length);
Parcel p = Parcel.obtain();
p.setDataPosition(0);
p.appendFrom(parcel, offset, length);
if (DEBUG) Log.d(TAG, "Retrieving " + Integer.toHexString(System.identityHashCode(this))
+ ": " + length + " bundle bytes starting at " + offset);
p.setDataPosition(0);
mParcelledData = p;
}
}
疑问:
如果不使用Intent意图跳转来使用Parcelable,如何手动序列化和反序列化?
以下获取的newCar为null
Parcel mParcel = Parcel.obtain(); final Car mCar = new Car(mParcel); Car.model = "Lamborghini"; mCar.setColor("while"); mCar.setPrice(9999999); mCar.setUser("my wife"); mCar.setAddress("China"); //序列化 mCar.writeToParcel(mParcel, 0); Car newCar =mParcel.readParcelable(null); Log.d(TAG, "readParcelable :" + newCar.toString());
static 和 transient 修饰的变量是否参与Parcelable序列化?
- Parcel与Binder的关系?
参考:
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0204/2410.html
https://blog.csdn.net/chzphoenix/article/details/79799289
http://www.droidsec.cn/%E5%BD%BB%E5%BA%95%E7%90%86%E8%A7%A3android-binder%E9%80%9A%E4%BF%A1%E6%9E%B6%E6%9E%84/
https://blog.csdn.net/caowenbin/article/details/6532217
https://blog.csdn.net/rainbowchou/article/details/54294394