日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

《克隆人的进攻》面向对象Java版

發布時間:2024/3/12 java 55 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《克隆人的进攻》面向对象Java版 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Java Q&A - Java 問答 - Attack of the clones - 克隆人的進攻 之 面向對象Java版

Java Q&A
Java 問答

Attack of the clones

克隆人的進攻

之 面向對象Java版

Time and space considerations in four different approaches to implementing deep clone() methods

權衡時間和空間的得失,有四種不同的方案來實現 deep clone() 方法。

By Vladimir Roubtsov
K ][ N G of A R K? 編譯 [Revision 0.1]


January 24, 2003
二零零三年一月二十四日

Q:What are the advantages and disadvantages of implementing deep cloning via Java serialization and a built-in Object.clone() method from a performance point of view?
問:從性能的角度觀之, 以 Java serialization(次第讀寫)或者內建的 Object.clone() 方法(method)來實現 deep cloning(深度克隆),各有哪些優劣之處?

A:Equipping classes in your application with correct clone() implementation is essential to many defensive programming patterns. Common examples include defensive copying of method parameters, cloning internal fields before returning them in getters, implementing immutability patterns, implementing containers with deep cloning semantics, and so on.
答:在您的應用程序中為各個類別搭載正確實現了的 clone() 方法,這對于許多防御式編程模式而言是至關重要的。常見的防御式編程模式包括:防御式的對方法接收的參數進行拷貝;從getters返回內部字段(field)之前先對該內部字段進行克隆;實現提供不可變功能的模式(immutability patterns);以 deep cloning(深度克隆)語義實現 containers(容器);等等。

Even though the question mentions just two possibilities, there are at least four distinct approaches to clone() implementation. In this Java Q&A installment, I consider design and performance tradeoffs involved in all of them.
盡管問題中只提到了兩個可能的方案,其實至少有四種不同的方案來實現 clone() 方法。在本期的Java 問答中,我就針對這四種方案來進行設計和性能兩方面的權衡。

Because cloning is so customizable, this article's examples will not necessarily translate directly to your own code; however, the general conclusions we will reach should provide useful guidelines in any application design.
由于克隆實現代碼的可定制性很強,因此本文的示例代碼不一定就適合直接轉化到您自己的代碼中;然而,我們得出的普適結論應該能為任何應用設計提供有用的指導。

Note the following disclaimer: What exactly constitutes a deep clone is debatable. Even though two objects can safely share the same String reference viewed as data, they cannot if the same field is used as an instance-scoped object monitor (such as when calling Object.wait()/notify() on it) or if field instance identity (such as when using the == operator) is significant to the design. In the end, whether or not a field is shareable depends on the class design. For simplicity, I assume below that all fields are used as pure data.
請注意這面這句不作承諾的聲明:deep clone(深度克隆)究竟有哪些具體的實現要素,這個問題本身就具有爭議性。盡管一個被視為數據的“String 引用”可以被兩個對象安全的共享,但如果該 String 字段是被用作實體生存空間范圍內(instance-scoped)的對象監視器(object monitor,比如對其調用 Object.wait()/notify() 的情形),或者字段實體的身份(identity)對于設計而言至關重要(比如使用 == operator 的情形),那么它就無法被安全的共享了。一言以蔽之,字段是否可被共享取決于類別的設計。為了簡單起見,我假設本文所述的所有字段都被視為純粹的數據來使用。

Performance measurements setup
用于性能度量的范例設定
Let's jump right into some code. I use the following simple hierarchy of classes as my cloning guinea pig:
讓我們直接來看些代碼。我使用如下簡單的類別階層體系來作為克隆“實驗鼠”:

public class TestBaseClass
???????????? implements Cloneable, Serializable
{
????public TestBaseClass (String dummy)
????{
????????m_byte = (byte) 1;
????????m_short = (short) 2;
????????m_long = 3L;
????????m_float = 4.0F;
????????m_double = 5.0;
????????m_char = '6';
????????m_boolean = true;

????????m_int = 16;
????????m_string = "some string in TestBaseClass";
????????
????????m_ints = new int [m_int];
????????for (int i = 0; i < m_ints.length; ++ i) m_ints [i] = m_int;
????????
????????m_strings = new String [m_int];
????????m_strings [0] = m_string; // invariant: m_strings [0] == m_string
????????for (int i = 1; i < m_strings.length; ++ i)
????????????m_strings [i] = new String (m_string);
????}

????public TestBaseClass (final TestBaseClass obj)
????{
????????if (obj == null) throw new IllegalArgumentException ("null input: obj");
????????
????????// Copy all fields:
????????
????????m_byte = obj.m_byte;
????????m_short = obj.m_short;
????????m_long = obj.m_long;
????????m_float = obj.m_float;
????????m_double = obj.m_double;
????????m_char = obj.m_char;
????????m_boolean = obj.m_boolean;
????????
????????m_int = obj.m_int;
????????m_string = obj.m_string;
????????
????????if (obj.m_ints != null) m_ints = (int []) obj.m_ints.clone ();
????????if (obj.m_strings != null) m_strings = (String []) obj.m_strings.clone ();
????}
????
????// Cloneable:
????public Object clone ()
????{
????????if (Main.OBJECT_CLONE)
????????{
????????????try
????????????{
????????????????// Chain shallow field work to Object.clone():
????????????????final TestBaseClass clone = (TestBaseClass) super.clone ();
????????????????
????????????????// Set deep fields:
????????????????if (m_ints != null)
????????????????????clone.m_ints = (int []) m_ints.clone ();
????????????????if (m_strings != null)
????????????????????clone.m_strings = (String []) m_strings.clone ();
????????????????
????????????????return clone;
????????????}
????????????catch (CloneNotSupportedException e)
????????????{
????????????????throw new InternalError (e.toString ());
????????????}
????????}
????????else if (Main.COPY_CONSTRUCTOR)
????????????return new TestBaseClass (this);
????????else if (Main.SERIALIZATION)
????????????return SerializableClone.clone (this);
????????else if (Main.REFLECTION)
????????????return ReflectiveClone.clone (this);
????????else
????????????throw new RuntimeException ("select cloning method");
????}
????
????protected TestBaseClass () {} // accessible to subclasses only
????

????private byte m_byte;
????private short m_short;
????private long m_long;
????private float m_float;
????private double m_double;
????private char m_char;
????private boolean m_boolean;

????private int m_int;
????private int [] m_ints;
????private String m_string;
????private String [] m_strings; // invariant: m_strings [0] == m_string????
} // end of class


public final class TestClass extends TestBaseClass
???????????? implements Cloneable, Serializable
{
????public TestClass (String dummy)
????{
????????super (dummy);
????????
????????m_int = 4;
????????
????????m_object1 = new TestBaseClass (dummy);
????????m_object2 = m_object1; // invariant: m_object1 == m_object2
????
????????m_objects = new Object [m_int];
????????for (int i = 0; i < m_objects.length; ++ i)
????????????m_objects [i] = new TestBaseClass (dummy);
????}

????public TestClass (final TestClass obj)
????{
????????// Chain to super copy constructor:
????????super (obj);
????????
????????// Copy all fields declared by this class:
????????
????????m_int = obj.m_int;
????????
????????if (obj.m_object1 != null)
????????????m_object1 = ((TestBaseClass) obj.m_object1).clone ();
????????m_object2 = m_object1; // preserve the invariant
????????
????????if (obj.m_objects != null)
????????{
????????????m_objects = new Object [obj.m_objects.length];
????????????for (int i = 0; i < m_objects.length; ++ i)
????????????????m_objects [i] = ((TestBaseClass) obj.m_objects [i]).clone ();
????????}
????}
????
????// Cloneable:
????public Object clone ()
????{
????????if (Main.OBJECT_CLONE)
????????{
????????????// Chain shallow field work to Object.clone():
????????????final TestClass clone = (TestClass) super.clone ();
????????????
????????????// Set only deep fields declared by this class:
????????????
????????????if (m_object1 != null)
????????????????clone.m_object1 = ((TestBaseClass) m_object1).clone ();
????????????clone.m_object2 = clone.m_object1; // preserve the invariant
????????????
????????????if (m_objects != null)
????????????{
????????????????clone.m_objects = (Object []) m_objects.clone ();
????????????????for (int i = 0; i < m_objects.length; ++ i)
????????????????????clone.m_objects [i] = ((TestBaseClass) m_objects [i]).clone ();
????????????}

????????????return clone;
????????}
????????else if (Main.COPY_CONSTRUCTOR)
????????????return new TestClass (this);
????????else if (Main.SERIALIZATION)
????????????return SerializableClone.clone (this);
????????else if (Main.REFLECTION)
????????????return ReflectiveClone.clone (this);
????????else
????????????throw new RuntimeException ("select cloning method");
????}
????????
????protected TestClass () {} // accessible to subclasses only

????private int m_int;????????
????private Object m_object1, m_object2; // invariant: m_object1 == m_object2
????private Object [] m_objects;
} // End of class

TestBaseClass has several fields of primitive types as well as a String and a couple of array fields. TestClass both extends TestBaseClass and aggregates several instances of it. This setup allows us to see how inheritance, member object ownership, and data types can affect cloning design and performance.
TestBaseClass 擁有幾個基本型別(primitive types)的字段(fields),還有一個 String 以及兩個數組。 TestClass 繼承自 TestBaseClass ,還聚合了幾個 TestBaseClass 實體。這種范例設定可以讓我們看到繼承、成員對象所有權(ownership)以及數據類型如何會影響克隆方法的設計與性能。

In a previous Java Q&A article, I developed a simple timing library that comes in handy now. This code in class Main measures the cost of TestClass.clone():
在 上一期 Java 問答 中,我開發了一個簡單的計時程序庫,現在可以信手拈來使用。在 class Main 中的如下代碼測量了 TestClass.clone() 的時間消耗:

????????// Create an ITimer:
????????final ITimer timer = TimerFactory.newTimer ();
????????
????????// JIT/hotspot warmup:
????????// ...

????????TestClass obj = new TestClass ();
????????
????????// Warm up clone():
????????// ...

????????final int repeats = 1000;
????????
????????timer.start ();
????????// Note: the loop is unrolled 10 times
????????for (int i = 0; i < repeats / 10; ++ i)
????????{
????????????obj = (TestClass) obj.clone ();
????????????... repeated 10 times ...
????????}
????????timer.stop ();
????????
????????final DecimalFormat format = new DecimalFormat ();
????????format.setMinimumFractionDigits (3);
????????format.setMaximumFractionDigits (3);
????????
????????System.out.println ("method duration: " +
????????????format.format (timer.getDuration () / repeats) + " ms");

I use the high-resolution timer supplied by TimerFactory with a loop that creates a moderate number of cloned objects. The elapsed time reading is reliable, and there is little interference from the garbage collector. Note how the obj variable continuously updates to avoid memory caching effects.
我使用了由 TimerFactory 提供的高解析度的計時器(high-resolution timer),利用一個循環創建了相當數量的克隆出來的對象。表示流逝時間的數據是可靠的,受垃圾收集器的影響很小。請注意 obj 變量被持續更新,以避免內存緩沖效應(memory caching effects)。

Also note how clone() is implemented in both classes. The implementation in each class is in fact four, selected one at a time using four conditional compilation constants in Main: OBJECT_CLONE, COPY_CONSTRUCTOR, SERIALIZATION, and REFLECTION. Recompile the entire object when changing the cloning approach.
還請注意,在兩個類別中都實現了 clone() 方法。實際上每個類別中都有四種克隆動作的實現,可以通過 Main 里面的條件編譯常量(conditional compilation constants)來選擇施行其中之一,這些常量分別是: OBJECT_CLONE,COPY_CONSTRUCTOR,SERIALIZATION 以及 REFLECTION 。要改變克隆動作的實現方案,需要重新編譯整個類別。

Let's now examine each approach in detail.
現在我們就分別詳細的審視前述的四個方案。

Approach 1: Cloning by chaining to Object.clone()

方案 1:通過串鏈 Object.clone() 實現克隆

This is perhaps the most classical approach. The steps involved are:
這或許就是最經典型的方案了。該方案涉及的實現步驟為:

  • Declare your class to implement the Cloneable marker interface.
  • 令您的類別實現 Cloneable 標記接口(marker interface)。
  • Provide a public clone override that always begins with a call to super.clone() followed by manual copying of all deep fields (i.e., mutable fields that are object references and cannot be shared between several instances of the parent class).
  • 提供一個覆寫(override)版本的 public clone 方法,其內以調用 super.clone() 開頭,后面再接續拷貝所有深層字段(deep fields,即為對象引用,且不能共享于多個父輩類別實體之間的可變字段(mutable fields))的代碼。
  • Declare your clone override not to throw any exceptions, including CloneNotSupportedException. To this effect, the clone() method in your hierarchy's first class that subclasses a non-Cloneable class will catch CloneNotSupportedException and wrap it into an InternalError.
  • 聲明該覆寫(override)版本的 clone 方法不拋出任何異常,包括不能拋出 CloneNotSupportedException 異常。 意思就是說:在您的類別階層體系中,對于第一個派生自 non-Cloneable 類別的那個類別,其 clone() 方法能夠捕獲 CloneNotSupportedException 異常并將該異常包入 InternalError 中。

Correct implementation of Cloneable easily deserves a separate article. Because my focus is on measuring performance, I will repeat the relevant points here and direct readers to existing references for further details (see Resources).
光是 Cloneable 的正確實現方法就可以很容易的需要占用另外一整篇文章的篇幅來進行闡述。鑒于我在這里關注的是性能的測量,因而我也就只復述一些相關的要點,并為讀者您提供更多細節的參考信息(詳見參考資源)。

This traditional approach is particularly well suited to the presence of inheritance because the chain of super.clone() eventually calls the native java.lang.Object.clone() implementation. This is good for two reasons. First, this native method has the magic ability to always create an instance of the most derived class for the current object. That is, the result of super.clone() in TestBaseClass is an instance of TestClass when TestBaseClass.clone() is part of the chain of methods originating from TestClass.clone(). This makes it easy to implement the desirable x.clone().getClass() == x.getClass() invariant even in the presence of inheritance.
這個經典型的方案特別適用于有繼承體系的地方,因為 super.clone() 串鏈最終會導致調用原生的 java.lang.Object.clone() 方法。說這樣做很妥當有兩個原因。其一,該原生方法(native method)具有神奇的能力,總是能夠為當前對象創建繼承體系最末端的類別實體。這就是說,TestBaseClass 中 super.clone() 的執行結果得到 TestClass 實體,因為 TestBaseClass.clone() 是起源自 TestClass.clone() 的一系列串鏈起來的方法之一。這樣一來,即使是在繼承體系之中也很容易實現我們想要的 x.clone().getClass() == x.getClass() 不變式(invariant)。

Second, if you examine the JVM sources, you will see that at the heart of java.lang.Object.clone() is the memcpy C function, usually implemented in very efficient assembly on a given platform; so I expect the method to act as a fast "bit-blasting" shallow clone implementation, replicating all shallow fields in one fell swoop. In many cases, the only remaining manual coding is done to deeply clone object reference fields that point to unshareable mutable objects.
其二,如果您查看JVM源代碼的話,您會看到 java.lang.Object.clone() 的核心部分是C函數 memcpy ,這個函數是用目標平臺上非常高效的匯編代碼實現的;因此可以期望這個 java.lang.Object.clone() 方法的實現是以快速的“按比特狂做(bit-blasting)”之方式進行的淺度克隆(shallow clone),能夠迅捷的復制所有淺層字段(shallow fields)。這樣一來在許多情況下,所剩的唯一需要手工編寫的代碼就只用負責對“指向非共享、可易變對象(unshareable mutable objects)之引用”進行深度克隆。

Running the test with the OBJECT_CLONE variable set to true on a Windows 550-MHz machine with Sun Microsystems' JDK 1.4.1 produces:
將 OBJECT_CLONE 變量設為 true ,在一臺安裝了 Sun Microsystems JDK 1.4.1 的 Windows 550-MHz 機器上面運行測試程序就產生出如下結果:

clone implementation: Object.clone()
method duration: 0.033 ms

This is not bad for a class with multiple primitive and object reference fields. But for better insight, I must compare the result with other approaches below.
對于擁有多個基本型別字段和對象引用字段的類別而言,這不算壞。然而為了更好的考究問題,我須將此結果與下面其它方案進行比較才對。

Despite its advantages, this approach is plagued with problems due to poor java.lang.Object.clone() design. It cannot be used for cloning final fields unless they can be copied shallowly. Creating smart, deeply cloning container classes is complicated by the fact that Cloneable is just a marker interface, and java.lang.Object.clone() is not public. Finally, cloning inner classes does not work due to problems with outer references. See articles by Mark Davis and Steve Ball in Resources for some of the earliest discussions about this topic.
盡管該方案有自己的優勢,但設計欠佳的 java.lang.Object.clone() 方法使其備受折磨。除非 final 字段能被淺層拷貝,否則該方案就不能用于對 final 字段進行克隆的情形。由于 Cloneable 只是一個標記接口(marker interface),而 java.lang.Object.clone() 方法又不是 public ,因此創建既聰明又具有 deeply cloning(深度克隆)能力的 container classes(容器類別)變得復雜起來。最后,由于外圍引用(outer references)亦招致問題,因此該方案也無法運用于克隆內隱類別(inner classes)的情形。關于此議題的最早的討論,參見 參考資源 中 Mark Davis 和 Steve Ball 的文章。

Approach 2: Cloning via copy construction

方案 2: 通過拷貝構造動作進行克隆

This approach complements Approach 1. It involves these steps:
這是對方案1的增強補足方案,實現起來包含下列步驟:

  • For every class X, provide a copy constructor with signature X(X x).
  • 對于每個 class X ,以標記式(signature) X(X x) 來提供一個 copy constructor 。

  • Chain to the base class's copy constructor in all but the first class in your hierarchy. You can chain to clone() or directly to the base copy constructor. The former choice is more polymorphic and works when the base copy constructor is private, and the latter sometimes avoids the small cost of casting clone()'s return value to a specific type.
  • 將基類的拷貝構造函數(copy constructor)串鏈到類別階層體系的所有類別中,階層體系最頂端的第一個類除外。您可以將其串鏈到這些類的 clone() 方法中,或者直接串鏈到它們的基類的拷貝構造函數(copy constructor)中。前一種做法更具多態特性,在基類的拷貝構造函數(copy constructor)為private時即可湊效;后一種做法有時候能夠避免“將 clone() 方法的返回值轉型(cast)到某個特定型別”所帶來的微小性能消耗。

  • Following the chaining call, set all class fields by copying them from the input parameter. For every object reference field, you decide individually whether to clone it deeply.
  • 將上述調用串鏈起來之后,將輸入參數拷貝給所有的類別字段(fields)。接著由您自己來決定是否對各個對象引用字段進行深度克隆。

Setting COPY_CONSTRUCTOR to true and rerunning the test produces:
將 COPY_CONSTRUCTOR 設為 true ,再重新運行測試程序,產生如下結果:

clone implementation: copy construction
method duration: 0.024 ms

This beats Approach 1. The result might not be surprising because the overhead of native method calls has increased and the cost of new object creation has decreased with increasing JDK versions. If you rerun the same tests in Sun's JDK 1.2.2, the situation favors Approach 1. Of course, performance depends on the relative mix of shallow and deep fields in the class hierarchy. Classes with many primitive type fields benefit more from Approach 1. Classes with a few mostly immutable fields work very efficiently with Approach 2, with a speed advantage at least 10 times greater than Approach 1.
這次的結果意味方案2勝過方案1。或許這結果并不令人吃驚,因為增加了對原生方法的調用,而創建新對象的消耗伴隨著 JDK 版本的升高而減小。如果您在 Sun 公司的 JDK 1.2.2 之下重新運行相同的測試,方案1就會勝出。當然,性能依賴于類別階層體系中淺層字段(shallow fields)和深層字段(deep fields)的混雜方式。擁有很多基本型別之字段的類別會更多的得益于方案1。而對于只擁有少數字段且多為不可變字段的類別,方案2運作得非常高效,其速度上的優勢至少為快過方案1十倍。

Approach 2 is more error prone than Approach 1 because it is easy to forget to override clone() and accidentally inherit a superclass's version that will return an object of the wrong type. If you make the same mistake in Approach 1, the result will be less disastrous. Additionally, it is harder to maintain the implementation in Approach 2 when fields are added and removed (compare the OBJECT_CLONE branch in TestBaseClass.clone() with similar code in the copy constructor). Also, Approach 1 requires less class cooperation in some cases: for a base class with only shallow fields, you don't need to implement Cloneable or even provide a clone() override if you do not intend to clone at the base class level.
方案2比方案1更容易出錯,因為很容易忘記覆寫(override) clone() 方法,并由此意外的繼承了父輩類別(superclass)的 clone() 版本,其返回一個錯誤型別的對象。但若您在方案1中犯下同樣的錯誤,后果就不會那么慘重。另外,當類別的字段被添加或者刪除時,方案2的實現代碼更難于維護(將 TestBaseClass.clone() 中的 OBJECT_CLONE 分支與拷貝構造函數中的相應代碼進行比較即可知)。再有就是,方案1在某些情況下對類別之間的合作需求更少:對于只擁有淺層字段的基類,您不需要實現 Cloneable 方法;如果您無意在基類的層級上進行克隆動作,您甚至不需要提供覆寫版本的 clone() 方法。

However, an undeniable advantage of cloning via copy construction is that it can handle both final fields and inner classes. But due to dangers present when inheritance is involved, I recommend using this sparingly and preferably simultaneously with making the relevant classes final.
然而,通過拷貝構造動作進行克隆(譯注:即方案2)有個不可否認的優勢,此即:該方案既可以處理 final 字段,也可以處理內隱類別(inner classes)。鑒于該方案在涉及繼承時所具有的危險性,我建議保守的采用之,且采用該方案時最好同時將有關的類別聲明為final 。

Approach 3: Cloning via Java serialization

方案 3:通過 Java serialization(次第讀寫)進行克隆

Java serialization is convenient. Many classes are made serializable by simply declaring them to implement java.io.Serializable. Thus, a whole hierarchy of classes can be made cloneable by deriving them from a base Serializable class whose clone() is implemented as a simple, yet extremely generic method:
Java serialization(次第讀寫)方便好用。許多類別只要被簡單的聲明為“實現 java.io.Serializable” 就能具備 serializable 性質。于是,若令整個階層體系派生自基類 Serializable ,那么階層體系的所有類別就都能具備 cloneable 性質,欲使然只要求基類 Serializable 實現出一個簡單,同時又極為通用的 clone() 方法:

????public Object clone (Object obj)
????{
????????try
????????{
????????????ByteArrayOutputStream out = new ByteArrayOutputStream ();
????????????ObjectOutputStream oout = new ObjectOutputStream (out);
????????????oout.writeObject (obj);
????????????
????????????ObjectInputStream in = new ObjectInputStream (
????????????????new ByteArrayInputStream (out.toByteArray ()));
????????????return in.readObject ();
????????}
????????catch (Exception e)
????????{
????????????throw new RuntimeException ("cannot clone class [" +
????????????????obj.getClass ().getName () + "] via serialization: " +
????????????????e.toString ());
????????}
????}

This is so generic it can be used for cloning classes that can be written and added to your application by someone else long after you provide the base classes. But this convenience comes at a price. After switching TestBaseClass.clone() and TestClass.clone() to the SERIALIZATION branch I get:
這個實現是如此之通用,在您寫好基類很久以后,別人要將新編寫的類別加入您的應用程序時,還可以利用該方法來克隆那些新編寫的類別。然而這種便利性得來有代價。將 TestBaseClass.clone() 和 TestClass.clone() 之實現代碼切換到 SERIALIZATION 分支的情況下,我得到如下的結果:

clone implementation: serialization
method duration: 2.724 ms

This is roughly 100 times slower than Approaches 1 and 2. You probably would not want this option for defensive cloning of parameters of otherwise fast intra-JVM methods. Even though this method can be used for generic containers with deep cloning semantics, cloning a few hundred objects would make you see times in the one-second range: a doubtful prospect.
這比方案1和方案2慢了有100倍左右。如果您是在為本該很快的 intra-JVM 之 方法的參數作防御性的克隆,您大概不會希望采用這種方案。盡管該方法可被運用于帶有深度克隆語義的通用containers(容器),但像這樣克隆幾百個對象的話,您會得到1秒鐘范圍內的時間消耗——其應用前景令人生疑。

There are several reasons why this approach is so slow. Serialization depends on reflective discovery of class metadata, known to be much slower than normal method calls. Furthermore, because a temporary input/output (I/0) stream is used to flatten the entire object, the process involves UTF (Universal Transformation Format) 8-encoding and writing out every character of, say, TestBaseClass.m_string. Compared to that, Approaches 1 and 2 only copy String references; each copy step has the same small fixed cost.
該方案如此緩慢有幾個原因。首先,serialization(次第讀寫)機制系依靠類別元數據(metadata)的映像式探知動作(reflective discovery),已知它比普通的函數調用慢得多。更為甚之,由于serialization(次第讀寫)使用一個臨時的 輸入/輸出(I/0)串流(stream)來攤開(flatten)整個對象,因而整個過程涉及到 UTF8 編碼動作(UTF8-encoding,Universal Transformation Format)以及向外寫入被攤開的對象成分的每個字符(比如 TestBaseClass.m_string)。相比之下(再以 TestBaseClass.m_string 為例),方案1和方案2只需要拷貝 String 引用,且每次拷貝具有相同的固定的時間消耗。

What's even worse, ObjectOutputStream and ObjectInputStream perform a lot of unnecessary work. For example, writing out class metadata (class name, field names, metadata checksum, etc.) that may need to be reconciled with a different class version on the receiving end is pure overhead when you serialize a class within the same ClassLoader namespace.
更糟糕的是,ObjectOutputStream 和 ObjectInputStream 做了諸多不必要的工作。例如向外寫入類別元數據(metadata,這包括類別名稱、字段名稱、元數據校驗和,等等),只為與寫入操作之接收端的不同版本類別相配合,而這對于您在同一個 ClassLoader 命名空間(namespace)里面次第讀寫(serialize)類別的情況下,純粹就是額外負荷。

On the plus side, serialization imposes fairly light constructor requirements (the first non-Serializable superclass must have an accessible no-arg constructor) and correctly handles final fields and inner classes. This is because native code constructs the clone and populates its fields without using any constructors (something that can't be done in pure Java).
從好的一面來說,次第讀寫(serialization)對構造函數的特定需求相當小(第一個 non-Serializable 基類必須擁有一個可訪問的無參數構造函數),并能正確妥當的處理final字段和內隱類別的情形。這是因為原生代碼能在不使用構造函數的情況下構造克隆對象并轉存(populates)對象的字段(這是單純依靠Java所無法做到的)。

One more interesting advantage of Approach 3 is that it can preserve the structure of object graph rooted at the source object. Examine the dummy TestBaseClass constructor. It fills the entire m_strings array with the same m_string reference. Without any special effort on our part, the invariant m_strings[0] == m_string is preserved in the cloned object. In Approaches 1 and 2, the same effect is either purely incidental (such as when immutable objects remain shared by reference) or requires explicit coding (as with m_object1 and m_object2 in TestClass). The latter could be hard to get right in general, especially when object identities are established at runtime and not compile time (as is the case with TestClass).
方案3還有一個優勢:它可以保持根基于次第讀寫源對象的“對象圖面(object graph)”結構。來觀察一下 dummy TestBaseClass 構造函數。該構造函數以相同的 m_string 引用填充整個 m_strings 數組。在我們的代碼中,不用借助任何特殊動作就可以在克隆出來的對象內保持 m_strings[0] == m_string 不變式(invariant)。而要在方案1和方案2中達到同樣的效果,則要么純粹靠巧合(比如不可變對象通過引用保持被共享),要么就需要額外的編碼(如同 TestClass 中 m_object1 和 m_object2 的情形)。要把后一種情況做到正確無誤通常是困難的,特別是在對象的身份在運行期(而非編譯期)才建立之情形下(如 TestClass 中的情形)。

Approach 4: Cloning via Java reflection

方案 4:通過 Java reflection(映像)進行克隆

Approach 4 draws inspiration from Approach 3. Anything that uses reflection can work on a variety of classes in a generic way. If I require the class in question to have a (not necessarily public) no-arg constructor, I can easily create an empty instance using reflection. It is especially efficient when the no-arg constructor doesn't do anything. Then it is a straightforward matter to walk the class's inheritance chain all the way to Object.class and set all (not just public) declared instance fields for each superclass in the chain. For each field, I check whether it contains a primitive value, an immutable object reference, or an object reference that needs to be cloned recursively. The idea is straightforward but getting it to work well requires handling a few details. My full demo implementation is in class ReflectiveClone, available as a separate download. Here is the pseudo-code of the full implementation, with some details and all error handling omitted for simplicity:
方案4從方案3吸取了一些要領。針對各種類別,任何動用映像(reflection)者都能以通用的方式處理之。如果我希望手中的類別能擁有一個無參數構造函數(并非需要為 public),我用映像(reflection)簡單的創建一個空白實體即可。在無參數構造函數并不做任何事情的情況下,使用映像(reflection)就特別有效率。于是,我們可以直截了當的走遍類別的繼承鏈,一路直至 Object.class ,并在其間為繼承鏈中每一個基類設置所有聲明的實體字段(不僅只含 public 的字段)。我針對其中每一個字段做檢查,看其包含的是否為:基本型別的值,或不可變對象之引用,或是需要被遞歸克隆的對象引用。整個想法是直截了當的,但欲令其正確運作,我們需要處理幾個細節。我撰寫的完整范例實現在 ReflectiveClone 類別中,被作為一個單獨的 下載 供您查看。該完整實現的偽碼如下,為了簡單起見忽略了某些細節以及所有錯誤處理:

public abstract class ReflectiveClone
{
????/**
???? * Makes a??reflection-based deep clone of 'obj'. This method is mutually
???? * recursive with {@link #setFields}.
???? *
???? * @param obj current source object being cloned
???? * @return obj's deep clone [never null; can be == to 'obj']
???? */
????public static Object clone (final Object obj)
????{????????
????????final Class objClass = obj.getClass ();
????????final Object result;
????????????????
????????if (objClass.isArray ())
????????{??????????
????????????final int arrayLength = Array.getLength (obj);
????????????
????????????if (arrayLength == 0) // empty arrays are immutable
????????????????return obj;
????????????else
????????????{??????????????????????
????????????????final Class componentType = objClass.getComponentType ();
????????????????
????????????????// Even though arrays implicitly have a public clone(), it
????????????????// cannot be invoked reflectively, so need to do copy construction:
????????????????
????????????????result = Array.newInstance (componentType, arrayLength);
????????????????
????????????????if (componentType.isPrimitive () ||
????????????????????FINAL_IMMUTABLE_CLASSES.contains (componentType))
????????????????{
????????????????????System.arraycopy (obj, 0, result, 0, arrayLength);
????????????????}
????????????????else
????????????????{
????????????????????for (int i = 0; i < arrayLength; ++ i)
????????????????????{
????????????????????????// Recursively clone each array slot:
????????????????????????final Object slot = Array.get (obj, i);
????????????????????????if (slot != null)
????????????????????????{
????????????????????????????final Object slotClone = clone (slot);
????????????????????????????Array.set (result, i, slotClone);
????????????????????????}
????????????????????}
????????????????}
????????????????
????????????????return result;
????????????}
????????}
????????else if (FINAL_IMMUTABLE_CLASSES.contains (objClass))
????????{
????????????return obj;
????????}
????????
????????// Fall through to reflectively populating an instance created
????????// via a no-arg constructor:

????????// clone = objClass.newInstance () can't handle private constructors:
????????????
????????Constructor noarg = objClass.getDeclaredConstructor (EMPTY_CLASS_ARRAY);
????????if ((Modifier.PUBLIC & noarg.getModifiers ()) == 0)
????????{
????????????noarg.setAccessible (true);
????????}

????????result = noarg.newInstance (EMPTY_OBJECT_ARRAY);
????????
????????for (Class c = objClass; c != Object.class; c = c.getSuperclass ())
????????{
????????????setFields (obj, result, c.getDeclaredFields ());
????????}
????????
????????return result;
????}????

????/**
???? * This method copies all declared 'fields' from 'src' to 'dest'.
???? *
???? * @param src source object
???? * @param dest src's clone [not fully populated yet]
???? * @param fields fields to be populated
???? */
????private static void setFields (final Object src, final Object dest,
?????????????????????????????????? final Field [] fields)
????{
????????for (int f = 0, fieldsLength = fields.length; f < fieldsLength; ++ f)
????????{????????????
????????????final Field field = fields [f];
????????????final int modifiers = field.getModifiers ();
????????????
????????????if ((Modifier.STATIC & modifiers) != 0) continue;
????????????
????????????// Can also skip transient fields here if you want reflective
????????????// cloning to be more like serialization.
????????????
????????????if ((Modifier.FINAL & modifiers) != 0)
????????????????throw new RuntimeException ("cannot set final field" +
????????????????field.getName () + " of class " + src.getClass ().getName ());
????????????
????????????if ((Modifier.PUBLIC & modifiers) == 0) field.setAccessible (true);
????????????
????????????Object value = field.get (src);
????????????
????????????if (value == null)
????????????????field.set (dest, null);
????????????else
????????????{
????????????????final Class valueType = value.getClass ();
????????????????
????????????????if (! valueType.isPrimitive () &&
????????????????????! FINAL_IMMUTABLE_CLASSES.contains (valueType))
????????????????{
????????????????????// Value is an object reference, and it could be either an
????????????????????// array or of some mutable type: try to clone it deeply
????????????????????// to be on the safe side.
????????????????????????
????????????????????value = clone (value);
????????????????}
????????????????
????????????????field.set (dest, value);
????????????}
????????}
????}

????private static final Set FINAL_IMMUTABLE_CLASSES; // Set in
????private static final Object [] EMPTY_OBJECT_ARRAY = new Object [0];
????private static final Class [] EMPTY_CLASS_ARRAY = new Class [0];
????
????static
????{
????????FINAL_IMMUTABLE_CLASSES = new HashSet (17);
????????
????????// Add some common final/immutable classes:
????????FINAL_IMMUTABLE_CLASSES.add (String.class);
????????FINAL_IMMUTABLE_CLASSES.add (Byte.class);
????????...
????????FINAL_IMMUTABLE_CLASSES.add (Boolean.class);
????}
} // End of class

Note the use of java.lang.reflect.AccessibleObject.setAccessible() to gain access to nonpublic fields. Of course, this requires sufficient security privileges.
請注意,使用了 java.lang.reflect.AccessibleObject.setAccessible() 來獲得對 non-public 字段的訪問。當然,這也需要有足夠安全級別的權限才能為之。

Since the introduction of JDK 1.3, setting final fields via reflection is no longer possible (see Note 1 in Resources); so, this approach resembles Approach 1 because it can't handle final fields. Note also that inner classes cannot have no-arg constructors by definition (see Note 2 in Resources), so this approach will not work for them either.
自從 JDK 1.3 以來,通過映像(reflection)設置 final 字段就不再被允許了。(詳見參考資源中的注釋1);因此,本方案類似方案1,它無法處理 final 字段的情形。還請注意,內隱類別(inner classes)不能在其定義中含有無參數構造含數(詳見 參考資源中的注釋2),故本方案也無法處理內隱類別(inner classes)情形。

Coupled with the no-arg constructor requirement, this approach restricts the type of classes it can handle. But you would be surprised how far it can go. The full implementation adds a few useful features. While traversing the object graph rooted at the source object, it keeps an internal objMap parameter that maps values in source object graphs to their respective clones in the cloned graphs. This restores the ability to preserve object graphs that I had in Approach 3. Also, the metadataMap parameter caches class metadata for all classes that it encounters while cloning an object and improves performance by avoiding slow reflection. The relevant data structures are scoped to a single call to clone(), and the overall idea is very similar to Java serialization revamped to just do object cloning. Similar to the previous section, a whole hierarchy of suitable classes can be made cloneable by equipping the base class with one generic method:
該方案除了有“需要無參數構造函數”之要求,還對能夠處理的類別有所限制。但您也許會驚訝于其能夠做到什么程度。完整的 實現 中增加了幾個有用的功能。在遍歷根基于克隆源對象的對象圖面(object graph)過程中,該實現會保留一個內部的 objMap 參數,用來將克隆源對象之圖面中的值對應到其克隆目標對象的圖面中去。這樣做就回復了方案3中的那種“保持對象圖面”的能力。另外, metadataMap 參數用來緩存(caches)克隆過程中遇到的所有類別之元數據(metadata),以此盡量避免緩慢的影像(reflection)動作從而提高性能。相關數據結構的生存空間被限定在單獨的 clone() 調用之中,其總體想法非常類似于“為了讓其專做對象克隆而對 Java serialization(次第讀寫) 進行修補”。這里的情形類同前面的小節:為基類搭載一個通用的方法,就可讓整個相互搭配的類別階層體系具有 cloneable 性質:

????public Object clone ()
????{
????????return ReflectiveClone.clone (this);
????}

What is this method's performance? Rerunning the test with the REFLECTION branch selected produces:
這個方法的性能如何呢?以 REFLECTION 分支重新運行測試程序產生出如下結果:

clone implementation: reflection
method duration: 0.537 ms

This is roughly five times faster than straightforward serialization—not too bad for another generic approach. In terms of its performance and capabilities, it represents a compromise between the other three solutions. It can work very well for JavaBean-like classes and other types that usually do not have final fields.
這比直截了當型的次第讀寫方案大約快了5倍——作為一個通用的方案還不算太壞。從其性能和處理能力來考量,該方案代表了對另外三個解決方案的折衷. 對于 JavaBean 形式的類別以及其它通常沒有 final 字段的型別,該方案非常湊效。

Resource considerations

對資源的考量

Measuring memory overhead is more difficult than measuring performance. It should be obvious that the first two approaches shine in this area, as they instantiate only the data that will populate the cloned fields.
度量內存負荷比度量性能更為困難。在內存負荷方面,前兩個方案應該具有很明顯的優勢,因為其中只有用來轉存(populate)克隆字段的數據才會被具現化(instantiated)。

Cloning via serialization has an extra drawback that may have escaped your attention above. Even though serializing an object preserves the structure of the object graph rooted at that instance, immutable values will get duplicated across disjoint calls to clone(). As an example, you can verify for yourself that
您或許剛才還沒留意,通過次第讀寫(serialization)進行克隆還另有一個缺點。盡管次第讀寫對象時能夠保持根基于該實體的對象圖面(object graph)結構,不可變的值卻會在對 clone() 方法的單個調用過程中被復制。作為例證,您可以自行驗證:

????TestClass obj = new TestClass ("dummy");
????System.out.println (obj.m_string == ((TestClass) obj.clone ()).m_string);

will print false for Approach 3 only. Thus, cloning via serialization will have a tendency to pollute heap with redundant copies of immutable objects like Strings. Approaches 1 and 2 are completely free from this problem, and Approach 3 is mostly free from it.
其結果僅在采用方案3時列印出 false 。如此看來,通過次第讀寫(serialization)進行克隆就具有傾向性,容易產生冗余的諸如 Strings 這樣的不可變對象,從而污染堆(heap)空間。方案1和方案2中完全不存在這個問題,而方案3中則是幾乎不存在這個問題。

A quick and dirty proof of these observations can be seen by changing the body of Main.main() to keep the clones in memory and track the object count when a given heap size is reached:
有個蹩腳又便宜的辦法來證實上面的發現,只要改變 Main.main() 函數體,令其在內存中保留克隆體,并在堆空間增長到一定大小時追蹤對象計數即可:

????????int count = 0;
????????List list = new LinkedList ();
????????try
????????{
????????????while (true)
????????????{
????????????????list.add (obj.clone ());
????????????????++ count;
????????????}
????????}
????????catch (Throwable t)
????????{
????????????System.out.println ("count = " + count);
????????}

Run this in a JVM with a -Xmx8m setting and you will see something similar to this:
若在 JVM 中以 -Xmx8m 設置來運行上述代碼,您將看到類似如下的結果:

>java -Xmx8m Main
clone implementation: Object.clone()
count = 5978 Exception in thread "main" java.lang.OutOfMemoryError
...
clone implementation: copy construction
count = 5978
...
clone implementation: serialization
count = 747
...
clone implementation: reflection
count = 5952

Approach 3's overhead increases with the number of immutable fields in a class. Removing this overhead is nontrivial.
方案3的負荷隨著類別中不可變字段(immutable fields)數量的增加而增加。消除該負荷則需要一些心力。

The recap

摘要列表

The following table recaps the properties of all cloning approaches in this article from several perspectives: speed, resource utilization, class design constraints, object graph handling.
下面的表格從幾個方面整理了本文中所有克隆方案,這些方面包括:速度;資源利用率;類別設計上的約束;對象圖面掌控情況。

Object.clone()
SpeedHigh
Resource utilizationLow
Class design constraintsDoes not work with deep final fields; does not work with inner classes; must implement Cloneable; medium amount of manual class maintenance
Object graphsDoes not handle object graphs transparently
Copy construction
SpeedHigh
Resource utilizationLow
Class design constraintsSuperclasses and subclasses must cooperate; copy constructor required; a lot of manual class maintenance
Object graphsDoes not handle object graphs transparently
Serialization
SpeedLow
Resource utilizationHigh; creates redundant immutable fields
Class design constraintsMust implement Serializable; first non-Serializable class needs an accessible no-arg constuctor
Object graphsHandles object graphs
Reflection
SpeedMedium
Resource utilizationMedium
Class design constraintsDoes not work with final fields; does not work with inner classes; each class must provide no-arg constructor
Object graphsHandles object graphs

Object.clone()
速度
資源利用率
類別設計上的約束不能應用于深層final字段的情形;不能應用于內隱類別(inner class)的情形;必須實現 Cloneable 接口;類別的手動維護所需工作量適中。
對象圖面不能透明的掌控對象圖面。
拷貝構造動作
速度
資源利用率
類別設計上的約束基類和子類必須相互協作配合;需要拷貝構造函數;類別的維護所需工作量大。
對象圖面不能透明的掌控對象圖面。
Serialization
速度
資源利用率高;創建冗余的不可變(immutable)字段
類別設計上的約束必須實現 Serializable 接口;第一個 non-Serializable 類別需要一個可訪問的無參數構造函數。
對象圖面掌控對象圖面。
Reflection
速度適中
資源利用率適中
類別設計上的約束不能應用于final字段的情形;不能應用于內隱類別(inner class)的情形;類別必須提供無參數構造函數。
對象圖面掌控對象圖面。

This article discussed implementing a single method, Object.clone(). It is amazing that a single method can have so many implementation choices and subtle points. I hope this article provided you with some food for thought and useful guidelines for your application class design.
本文討論了 Object.clone() 這單獨一個方法的實現。令人驚異的是,一個方法竟然可以有這么多種實現方案和這么多微妙的細節要點。我希望本文帶給您一些思考的素材,并為您的應用程序之類別設計提供了有用指導。


About the author
關于作者
Vladimir Roubtsov has programmed in a variety of languages for more than 12 years, including Java since 1995. Currently, he develops enterprise software as a senior developer for Trilogy in Austin, Texas.
Vladimir Roubtsov 具有超過十二年的多語言編程經驗,掌握的語言包括從1995就年開始使用的Java。目前他任職于德克薩斯州奧斯汀的 Trilogy 公司,作為高級開發人員進行企業級軟件的開發。

  • Resources
    相關資源
  • Download the complete source code that accompanies this article:
    http://www.javaworld.com/javaworld/javaqa/2003-01/clone/02-qa-0124-clone.zip
  • 在這里下載本文配套的源代碼:
    http://www.javaworld.com/javaworld/javaqa/2003-01/clone/02-qa-0124-clone.zip
  • The high-resolution library used for measurements in this article was developed in another Java Q&A installment:
    http://www.javaworld.com/javaworld/javaqa/2003-01/01-qa-0110-timing.html
  • 在本文用于測量時間的高解析度程序庫是在另一期Java 問答中開發出來的。
    http://www.javaworld.com/javaworld/javaqa/2003-01/01-qa-0110-timing.html
  • For more on cloning see "Hashing and Cloning," Mark Davis (Java Report, April 2000) pp. 60-66; "Effective Cloning," Steve Ball (Java Report, January 2000) pp. 60-67; "Solutions for Implementing Dependable Clone Methods," Steve Ball (Java Report, April 2000) pp. 68-82
  • 欲了解更多關于克隆技術的內容,請參見 "Hashing and Cloning," Mark Davis (Java Report, April 2000) pp. 60-66; "Effective Cloning," Steve Ball (Java Report, January 2000) pp. 60-67; "Solutions for Implementing Dependable Clone Methods," Steve Ball (Java Report, April 2000) pp. 68-82
  • Note 1: In Sun JDK 1.2 you could set even final fields using reflection as long as you used setAccessible(), but this changed in later Sun JDK versions.
  • 注釋 1:在 Sun JDK 1.2 中,只要您使用了 setAccessible() ,您甚至可以使用 reflection 機制來設置 final fields, 但是在后續的 Sun JDK 版本中,這個細節發生了變化。
  • Note 2: Syntactically an inner class may appear to have a no-arg constructor. However, in bytecode every constructor of an inner class takes at least one parameter that is a reference to the outer object. Note that by inner classes, I specifically mean non-static nested classes. Static nested classes do not have this problem.
  • 注釋 2:從語法的角度來說,內隱類別(inner class)可以擁有一個無參數的構造函數。然而在最終的 bytecode 里,內隱類別的每一個構造函數至少具有一個參數,即指向外層對象的一個引用(reference)。要注意,我這里談及的 inner classes 特別意指非靜態的內嵌類別(non-static nested classes)。靜態的內嵌類別(static nested classes)沒有上述問題。
  • Java 101's "Object-oriented language basics, Part 5" by Jeff Friesen (JavaWorld, August 2001) contains a section about cloning:
    http://www.javaworld.com/javaworld/jw-08-2001/jw-0803-java101.html
  • Java 101's "Object-oriented language basics, Part 5" by Jeff Friesen (JavaWorld, August 2001) 里面有一節關于克隆技術的內容:
    http://www.javaworld.com/javaworld/jw-08-2001/jw-0803-java101.html
  • Want more? See the Java Q&A index page for the full Q&A catalog:
    http://www.javaworld.com/columns/jw-qna-index.shtml
  • 還想看更多內容嗎?請瀏覽 Java 問答 的索引頁查看完整的問答集分類:
    http://www.javaworld.com/columns/jw-qna-index.shtml
  • For more than 100 insightful Java tips, visit JavaWorld's Java Tips index page:
    http://www.javaworld.com/columns/jw-tips-index.shtml
  • 欲學習超過100條的Java專家技巧,請訪問 JavaWorld's Java Tips 索引頁:
    http://www.javaworld.com/columns/jw-tips-index.shtml
  • Browse the Core Java section of JavaWorld's Topical Index:
    http://www.javaworld.com/channel_content/jw-core-index.shtml
  • 請瀏覽至 JavaWorld's Topical Index 的 Core Java 小節:
    http://www.javaworld.com/channel_content/jw-core-index.shtml
  • Get more of your questions answered in our Java Beginner discussion:
    http://forums.devworld.com/webx?50@@.ee6b804
  • 請到我們的 Java Beginner 論壇獲得更多自己問題的答案:
    http://forums.devworld.com/webx?50@@.ee6b804
  • Sign up for JavaWorld's free weekly email newsletters:
    http://www.javaworld.com/subscribe
  • 欲注冊訂閱 JavaWorld 免費的新聞郵件周刊請至:
    http://www.javaworld.com/subscribe
  • You'll find a wealth of IT-related articles from our sister publications at IDG.net
  • 您可以在我們的兄弟出版品 IDG.net 中找到豐富的IT相關文章。

  • 主要術語英漢對照表
    • base class, 基類
    • cast/casting, 轉型
    • chain/chaining, 串鏈
    • class, 類別
    • clone/cloning, 克隆
    • copy constructor, 拷貝構造函數
    • field, 字段
    • immutable, 不可變的
    • mutable, 可變的/易變的
    • override, 覆寫
    • parameter, 參數
    • reflection, 映像
    • reflective discovery, 映像式探知
    • serialization, 次第讀寫
    • superclass, 父輩類別/超類
    • subclass, 子輩類別/子類
    • type, 型別




總結

以上是生活随笔為你收集整理的《克隆人的进攻》面向对象Java版的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

亚洲综合精品视频 | 九九天堂| 一区二区三区四区精品视频 | 91人人射| 激情视频一区二区 | 日韩免费高清在线观看 | 欧美综合国产 | 日韩va亚洲va欧美va久久 | 丁香花在线视频观看免费 | 日韩国产精品久久久久久亚洲 | 中文字幕麻豆 | 免费在线播放黄色 | 在线看v片| 中文不卡视频在线 | 欧美午夜a| 亚洲小视频在线 | 天天操天天能 | 免费网站看av片 | 国产成人久久 | 久久精品一区二区国产 | 久久久视屏 | 99久久婷婷国产综合精品 | 99视频国产在线 | 国产午夜激情视频 | 国产精品一区二区美女视频免费看 | 色多多视频在线观看 | 久久福利小视频 | 在线国产激情视频 | 国产日产精品一区二区三区四区的观看方式 | 成人网中文字幕 | 99精品视频在线 | 国产精品美女久久久网av | 婷婷丁香自拍 | 色婷婷视频在线 | 欧美日韩亚洲第一页 | 国产资源精品 | 天天爱天天射天天干天天 | 91人人爽人人爽人人精88v | 最近最新最好看中文视频 | 国内成人精品视频 | 久久久国产日韩 | 欧美精品久久久久久久亚洲调教 | 美女搞黄国产视频网站 | 精品国产aⅴ麻豆 | 国产精品国产三级国产 | 日韩二区三区在线 | 99re热精品视频 | 欧美日韩在线观看一区二区三区 | 免费视频二区 | 欧美xxxxx在线视频 | 精品久久久99 | 中文字幕av最新 | 婷婷av网 | 日日日日| 久久久久久久国产精品影院 | 亚洲影视九九影院在线观看 | 麻豆视频免费播放 | 激情av资源 | 开心激情五月婷婷 | 久草在线观看视频免费 | 日韩在线观看网站 | 四虎5151久久欧美毛片 | 国产成人精品午夜在线播放 | 亚洲一区欧美精品 | 大胆欧美gogo免费视频一二区 | 国产一区免费在线 | 久久这里只精品 | 毛片激情永久免费 | 久久99久久99精品免观看软件 | 日韩精品久久久久久久电影99爱 | 国产在线精 | 一区二区三区韩国免费中文网站 | 国产又粗又猛又黄又爽的视频 | 日韩av免费一区 | 免费在线观看黄 | 日韩中文字幕免费 | 国产又粗又猛又黄又爽 | 成人久久综合 | 国产精品美女久久久久久久久 | 狠狠色丁香久久婷婷综合丁香 | 91av综合| 狠狠色伊人亚洲综合网站色 | 天堂中文在线播放 | 日韩乱色精品一区二区 | 色视频成人在线观看免 | 日韩簧片在线观看 | 日日夜夜天天综合 | 亚洲精品乱码久久久久久9色 | 日韩av美女| 欧美色综合天天久久综合精品 | 欧美日韩一区二区三区在线免费观看 | 人人爱人人射 | 91精品国自产在线观看欧美 | 中文字幕有码在线观看 | 久久看免费视频 | 69精品 | 美女国产网站 | av成人在线电影 | 国内视频在线 | 国产精品久免费的黄网站 | 婷婷丁香导航 | 婷婷中文字幕综合 | 日本黄色免费在线 | 国产18精品乱码免费看 | 亚洲精品在线观看网站 | 亚洲欧美国产精品va在线观看 | 久久av伊人 | 特级黄色视频毛片 | 久久人人精 | 欧美一级xxxx | 亚洲精品黄色在线观看 | 成人禁用看黄a在线 | 99精品久久只有精品 | 国产精品手机在线播放 | 玖玖爱国产在线 | 91精品视频在线免费观看 | 国产色一区| 久久久久久久国产精品 | 天天操天天操 | 亚洲影视九九影院在线观看 | 久久视精品 | 久久不卡av| 免费黄a| 69av视频在线 | 懂色av一区二区三区蜜臀 | 亚洲精品视频免费在线 | 精品久久国产 | 久久久久久久久久影院 | 一级黄色a视频 | 国产精品毛片一区视频 | 国产成人精品三级 | 伊人婷婷网 | 国产精品国产三级国产不产一地 | 免费色视频 | 久久久久国产免费免费 | 欧美在线一| 中文字幕在线影视资源 | 色网av | 亚洲情婷婷 | 国产视频2区 | 日日爽视频 | 亚洲情影院 | 91视频午夜 | 91精品国产91久久久久 | 日韩免费观看av | 欧美日韩久久不卡 | 国产亚洲欧美精品久久久久久 | 久久人人爽视频 | 日韩午夜一级片 | 日韩三级精品 | 黄色av高清 | 国产精品久久网站 | 久久福利小视频 | 天堂av网址 | 亚洲污视频 | 国产精品第二十页 | 国产福利av | 91.dizhi永久地址最新 | 91色视频| 人人干免费 | 在线观看久久久久久 | 久久久高清一区二区三区 | 天天干天天草 | 国产五月婷 | 亚洲精品av中文字幕在线在线 | 欧美一区在线观看视频 | 色综合久久久久综合体 | 香蕉97视频观看在线观看 | 国产一区二区三区在线 | 丁香婷婷电影 | 日韩中文字幕a | 99久久精品国产一区二区成人 | 黄色的视频网站 | 国产精品久久久av | 久久黄色小说 | 久久综合五月天 | 国产美女免费视频 | 国产成人精品不卡 | 久久黄色网址 | 超碰国产在线观看 | 日韩视频免费播放 | 一区免费观看 | 中文日韩在线 | 狠狠狠狠干 | 日本精品视频一区 | 亚洲黄色免费观看 | 中文字幕av免费在线观看 | 日韩视频免费在线 | 在线国产视频一区 | 欧美激情精品久久 | 热久精品 | 91亚洲精品久久久中文字幕 | 有码中文字幕在线观看 | 爱爱av在线 | 日本久久久久久久久久久 | 国产午夜精品福利视频 | 国产中文字幕免费 | 久久一级电影 | 天天干,夜夜操 | 日韩午夜电影网 | 欧美久久久久 | 亚洲精选视频在线 | 人人射人人爽 | www.久艹 | 国产精品亚 | 欧美网站黄色 | 欧美影片| 久久伊人五月天 | 黄污网站在线 | 香蕉在线影院 | .精品久久久麻豆国产精品 亚洲va欧美 | 亚洲国产电影在线观看 | 91人人揉日日捏人人看 | 手机av电影在线观看 | 国产一二三四在线视频 | 亚洲观看黄色网 | 国产精品一区在线观看你懂的 | 又黄又爽的视频在线观看网站 | 美女网站在线观看 | 91视频麻豆视频 | www.日日日.com| 丁香高清视频在线看看 | 91亚洲精品久久久久图片蜜桃 | 久久久久亚洲国产精品 | 色视频网站在线 | 337p日本欧洲亚洲大胆裸体艺术 | 久草在线费播放视频 | 国产成人精品一区在线 | 夜夜操狠狠干 | 在线中文视频 | 久草在线手机视频 | 国产午夜在线观看视频 | 中文有码在线视频 | 国产精品成人免费精品自在线观看 | 久久精品官网 | 美女禁18| 五月花婷婷 | 亚洲视频电影在线 | 国产一区二区三精品久久久无广告 | 久久精品三级 | 久久精品国亚洲 | 91丨九色丨国产丨porny精品 | 一本—道久久a久久精品蜜桃 | 99在线高清视频在线播放 | www.888av| 狠狠狠色狠狠色综合 | 一区二区久久 | 日日爽夜夜爽 | 日韩一级片观看 | www久久久 | 日产av在线播放 | 蜜臀av.com| 久久久久久久久久久久久久电影 | 免费在线观看成人av | 日韩美女黄色片 | av中文在线观看 | 97电影手机版 | 国产精品美女久久久久久久网站 | 99成人免费视频 | 精品国产美女 | 精品主播网红福利资源观看 | 欧美成人播放 | 欧美在线91| 欧美日在线观看 | 色综合亚洲精品激情狠狠 | 五月天堂网 | 国产精品麻豆视频 | 日本久久久精品视频 | 亚洲高清av在线 | 色播五月激情五月 | 久久精品一区二区三区视频 | 99视频在线精品免费观看2 | 国内成人综合 | 国产视频不卡一区 | 亚洲在线不卡 | 九九热只有这里有精品 | 婷婷资源站 | 91麻豆精品 | 日韩色视频在线观看 | av在线网站大全 | 91在线精品一区二区 | 精品96久久久久久中文字幕无 | 久久人人97超碰国产公开结果 | 国产精品免费视频一区二区 | 开心婷婷色| 夜添久久精品亚洲国产精品 | 久久精视频 | 欧美日韩在线视频一区二区 | 亚洲黄色在线免费观看 | 亚洲成人免费观看 | 欧美日韩国产一区二区三区 | 国产91在线观 | 天天爱天天色 | 天天色天天爱天天射综合 | 国产一级二级在线 | av福利免费 | 在线国产精品视频 | 国产 日韩 在线 亚洲 字幕 中文 | 日本性久久 | 毛片永久新网址首页 | 国产一区精品在线 | 91日韩精品视频 | 中文字幕制服丝袜av久久 | 91亚洲综合 | 在线视频精品 | 久久蜜桃av| 久久久久亚洲精品国产 | 九色福利视频 | 日韩在线观看你懂的 | 九九在线免费视频 | 日本九九视频 | 久久免费中文视频 | 999热线在线观看 | 亚洲精品视频在线观看网站 | 欧美精品国产综合久久 | 97超碰人 | 久草电影在线 | av在线之家电影网站 | 久久久精品网站 | 国产黄色一级片在线 | 精品亚洲一区二区 | 亚洲h在线播放在线观看h | 国产精品综合久久久 | 91精品久久久久久久久久入口 | 91人人射 | 国产精品久久久久久久久久新婚 | 欧美日韩视频网站 | 一区在线电影 | 日韩天堂网 | 在线看污网站 | 日p视频在线观看 | 欧美精品亚洲精品日韩精品 | 又黄又爽又色无遮挡免费 | 伊人婷婷综合 | 日韩和的一区二在线 | 久久看视频 | av免费电影网站 | 国产日韩欧美视频在线观看 | 在线视频观看成人 | 久久久久久高潮国产精品视 | 久久综合影音 | 精品福利在线 | 国产成人综合在线观看 | 特级毛片网 | 欧美精品九九99久久 | 中文字幕久久精品亚洲乱码 | 婷婷色社区 | 日韩精品一二三 | 天天操天天能 | 国产精品国产三级国产不产一地 | 一区二区三区免费在线 | 九九久久久久久久久激情 | 久久综合色一综合色88 | 色网站在线免费观看 | 永久av免费在线观看 | 少妇高潮流白浆在线观看 | 蜜臀av夜夜澡人人爽人人桃色 | 成人亚洲欧美 | 精品久久一区二区三区 | www.伊人色.com| 91福利视频在线 | 狠狠色丁香久久婷婷综合五月 | 日韩黄色免费 | 在线国产黄色 | 日日干日日色 | 亚洲高清在线观看视频 | 久久精品国产亚洲aⅴ | 精品天堂av | 最新中文字幕在线观看视频 | 色婷婷啪啪免费在线电影观看 | 天天色.com| 精品国产成人在线影院 | 亚洲日本在线视频观看 | 91香蕉视频黄 | 免费在线观看av网站 | 色婷婷色 | 日日夜夜网 | 久久久久激情电影 | 狠狠干夜夜 | 亚洲精品视频中文字幕 | 日本二区三区在线 | 久在线观看视频 | av在线免费观看黄 | 美女久久视频 | 久久国产热视频 | 精品久久久99 | 亚洲人人av | 日韩有码中文字幕在线 | 91丨九色丨91啦蝌蚪老版 | 在线视频91| 亚洲另类交 | 亚洲一二视频 | 丁香六月在线观看 | 国产精品第一视频 | 日韩精品久久久免费观看夜色 | 亚洲精品美女在线 | 粉嫩一二三区 | 摸阴视频| 亚洲欧美视频 | 国产精品资源在线 | 久久久69 | 91影视成人| 国产又粗又长又硬免费视频 | 丁香视频免费观看 | 亚洲精品成人av在线 | 亚洲精品乱码久久久久久蜜桃欧美 | 欧美久久久久 | 91av手机在线 | 日韩欧美综合视频 | 久久人人爽人人片 | 国产麻豆视频在线观看 | 亚洲精品国产精品国自产在线 | 日本精品一区二区三区在线播放视频 | 91视频啊啊啊 | 人人添人人澡人人澡人人人爽 | 97香蕉久久超级碰碰高清版 | 国产97视频 | 毛片3 | av片中文字幕 | 夜夜摸夜夜爽 | 玖玖视频免费在线 | 天天色天天爱天天射综合 | 久久精品国产第一区二区三区 | 九九精品毛片 | 99婷婷狠狠成为人免费视频 | 丰满少妇在线 | 久久久久久久国产精品影院 | 在线视频国产区 | 亚洲精品男人的天堂 | 91看片淫黄大片在线播放 | 日韩av高清 | 精品欧美一区二区在线观看 | 久久免费视频国产 | 精品在线不卡 | 久久久久久久久久福利 | 亚洲国产精品久久久久婷婷884 | 久草在线资源观看 | 国产在线观看xxx | 91大神电影| 日韩精品一区二区免费视频 | 亚洲天天做 | av一级一片| 99精品在线看 | 欧美日韩在线视频免费 | 亚洲不卡av一区二区三区 | 国产精品99久久久久久有的能看 | 国产精品久久久久久久久久久久久 | 国产精品毛片久久久久久 | 蜜桃av久久久亚洲精品 | 国产午夜精品一区二区三区嫩草 | 国产精品久久久久久久久免费看 | 999超碰| 最新国产精品亚洲 | 欧美日韩精品久久久 | 欧美在线观看视频 | 日日干天夜夜 | 国产精品视频免费看 | 日韩欧美在线视频一区二区三区 | av成人亚洲 | 天堂网一区二区 | 色九色| 91av影视 | 天天做日日爱夜夜爽 | 一级做a视频 | 成年人在线免费看视频 | 999成人网| 日韩中文字幕a | 亚洲欧美日韩一区二区三区在线观看 | 免费久久99精品国产婷婷六月 | 欧美 日韩精品 | 91精品啪在线观看国产线免费 | 国产美女被啪进深处喷白浆视频 | 国产精品99免视看9 国产精品毛片一区视频 | 91av视频在线免费观看 | 国产不卡一 | 久久亚洲电影 | 天天骚夜夜操 | 色瓜| 中文字幕在线免费 | 久久婷综合 | 欧美精品久久久 | 视频一区在线播放 | 中文在线免费一区三区 | 中文av字幕在线观看 | 欧美激情精品久久久久久变态 | 97香蕉久久超级碰碰高清版 | 免费福利在线播放 | 日韩精品中文字幕一区二区 | 久久99国产精品免费网站 | 黄色福利视频网站 | 91免费网站在线观看 | www.狠狠色| 99久久精品一区二区成人 | 97精品一区二区三区 | 五月婷婷中文网 | 中文字幕高清有码 | 国产精品成人久久久久久久 | 午夜国产成人 | 亚洲免费永久精品国产 | 国产精品一区二区三区四 | 国产精品免费看久久久8精臀av | 国产丝袜 | 四虎免费在线观看视频 | 亚洲免费婷婷 | 日韩精品中文字幕有码 | 日韩二区精品 | 一级黄色a视频 | 久久亚洲视频 | a色视频 | 亚洲视频免费在线看 | 色多多在线观看 | 国产黄色片一级三级 | 精品主播网红福利资源观看 | 欧美性春潮 | 欧美极品少妇xxxx | 国产精品成人一区二区三区吃奶 | 亚洲第一中文网 | 欧美精品久久久久久久免费 | 国产视频一二三 | www.天天操 | 久久精品99久久 | 91精品啪在线观看国产81旧版 | 日日射av | 亚洲精品美女久久17c | 久久综合免费 | 四虎影视成人精品国库在线观看 | 婷婷丁香在线视频 | 欧美最猛性xxx | 97超碰人人澡人人爱学生 | 久久激情视频 | 在线国产高清 | 亚洲精品免费观看视频 | 精品999久久久 | 欧美少妇xx| 国产伦理一区二区 | 亚洲日本在线一区 | 久久久.com| 亚洲一区精品二人人爽久久 | 中文字幕在线久一本久 | 国产精品美女网站 | 国产精品美女999 | 午夜色性片 | 中文字幕色在线视频 | 日本三级香港三级人妇99 | 国产精品亚州 | 国产一区视频免费在线观看 | 国产精品成人久久久久 | 国产中文字幕在线免费观看 | 日韩在线观看的 | 国产色道 | 国产一区二区电影在线观看 | 精品国产综合区久久久久久 | 四川bbb搡bbb爽爽视频 | 91爱看片| 国产亚洲欧美日韩高清 | 国产区久久 | 国产精品一区免费看8c0m | 久久无码av一区二区三区电影网 | 99爱这里只有精品 | 久久综合九色综合欧美狠狠 | 日韩一区二区三区高清免费看看 | 亚洲日本激情 | 国产午夜三级一二三区 | 999久久久久久久久6666 | 韩国一区二区av | 97超碰人人网 | 中文字幕日本在线 | 一区二区三区在线不卡 | 激情五月婷婷综合 | 日本中出在线观看 | 天天激情综合网 | 午夜在线免费观看 | 麻豆一精品传二传媒短视频 | 久久久亚洲影院 | 国产精品视频永久免费播放 | 日本色小说视频 | 夜色成人av | 精品在线观看一区二区 | 在线免费观看视频一区 | 国产日韩欧美在线播放 | 欧美成人一二区 | 激情网色 | 黄色亚洲| 欧美韩日在线 | 一区二区不卡在线观看 | 黄色网在线播放 | 日韩精品一区二区免费视频 | 激情视频亚洲 | 婷婷色社区 | 久草久草在线观看 | 国产成人综合精品 | 国内精品久久久久影院日本资源 | 婷婷在线网站 | 成人免费视频a | 天天天在线综合网 | 色资源二区在线视频 | 国产精品区一区 | 久久深夜福利免费观看 | 色噜噜在线观看 | 亚洲在线成人精品 | 精品亚洲午夜久久久久91 | 日韩三级不卡 | 日日干夜夜骑 | 久久久久 免费视频 | 欧美精品在线一区二区 | 日躁夜躁狠狠躁2001 | 久久夜靖品 | 欧美精品视| 中文免费观看 | av免费在线看网站 | 久久精品理论 | 91精品久久香蕉国产线看观看 | 狠狠黄| 国产精品wwwwww| 中文资源在线官网 | 国产日韩视频在线观看 | 激情深爱五月 | 国产精品久久久久久久久久新婚 | 亚洲精品午夜久久久久久久久久久 | 天天干人人干 | 亚洲视频播放 | 免费看一级特黄a大片 | 国产精品一区二区精品视频免费看 | 五月亚洲| 91一区二区三区在线观看 | 欧美999| 涩涩网站在线观看 | 99人久久精品视频最新地址 | 国产精品1区2区3区 久久免费视频7 | 五月婷婷在线视频观看 | 国产精品三级视频 | 国产成人久久77777精品 | 午夜精品一二区 | 97免费视频在线 | 久久免费99 | 色在线免费| 婷婷色在线| 欧美日韩中文国产一区发布 | 久久午夜色播影院免费高清 | 91污视频在线观看 | 女人18毛片a级毛片一区二区 | 亚洲一区二区三区91 | 国产区在线看 | 国产成人三级在线观看 | 中文字幕 国产精品 | 成人免费视频网站在线观看 | 999电影免费在线观看2020 | 亚洲区色 | 2019天天干夜夜操 | 成年人在线看视频 | 午夜精品久久久久久久久久久久 | 国产精品 中文在线 | 久久久精品免费观看 | 免费的成人av| 日韩一级网站 | 亚洲精品xxxx | 99精品久久久久久久久久综合 | 日本在线中文在线 | 天天操偷偷干 | 蜜臀av夜夜澡人人爽人人桃色 | 美女网站黄在线观看 | 99久久精品国产毛片 | 97超碰人人澡人人爱 | 久久久国产影视 | 国产精品一区二区三区久久 | 韩国av电影在线观看 | 2023天天干 | 日韩在线视频看看 | 中文字幕在线一区二区三区 | 中文字幕大全 | 黄色91免费观看 | 国产精品黄色av | 欧美成人久久 | 91入口在线观看 | 日本在线观看黄色 | 国产99精品在线观看 | 在线影视 一区 二区 三区 | 九九热精品视频在线观看 | 黄色福利视频网站 | 狠狠操夜夜操 | 欧美日韩91 | 亚洲午夜精品一区二区三区电影院 | av福利在线 | 黄色大全免费网站 | 中文字幕第一 | 久久精品欧美一区二区三区麻豆 | 中文字幕一区二区三区乱码在线 | 久综合网 | 欧美国产精品久久久久久免费 | 欧美乱淫视频 | 黄色国产在线观看 | 欧美一区二区三区免费观看 | 在线观看va| 精品久久亚洲 | 天天操网址 | 日本精品久久久一区二区三区 | 一区二区三区中文字幕在线观看 | 中文字幕视频观看 | 欧美片一区二区三区 | 日韩av一区二区三区在线观看 | 天天综合91 | 日日夜夜精品视频天天综合网 | a级国产乱理伦片在线观看 亚洲3级 | 怡春院av| 亚洲婷婷综合色高清在线 | 波多野结衣综合网 | www久久国产 | 国产精品麻豆免费版 | 99精品视频在线播放观看 | 国产精品美女在线观看 | 国产免费高清视频 | 国产精品自产拍在线观看桃花 | 伊人午夜视频 | 国产精品青草综合久久久久99 | 国产综合小视频 | 国产日韩欧美在线免费观看 | 免费观看性生交 | 国产视频色 | 国产91精品在线播放 | 99久久精品免费看国产麻豆 | 亚洲综合色网站 | 特级西西人体444是什么意思 | 日韩电影久久 | 日韩精品无码一区二区三区 | 色网站黄| 国产成人精品av久久 | 免费日韩在线 | 久久婷婷国产色一区二区三区 | 一级黄色大片在线观看 | 日韩电影在线观看中文字幕 | 特级xxxxx欧美| 亚洲精品在线一区二区三区 | 国产精品高潮在线观看 | 国产做a爱一级久久 | 国产精品亚洲成人 | 国产一区二区电影在线观看 | 国产精品手机在线观看 | v片在线播放| 日韩影视在线观看 | 国产在线视频在线观看 | 国产精品一区二区av影院萌芽 | 97色婷婷| 色噜噜日韩精品一区二区三区视频 | 日韩免费视频网站 | 中文字幕91在线 | 亚洲精品乱码久久久久v最新版 | aa一级片 | 欧美日韩国产综合网 | 成年人黄色大片在线 | 一区中文字幕电影 | 人人澡超碰碰 | 国产黄色免费观看 | 国产麻豆成人传媒免费观看 | 亚州精品成人 | 在线观看亚洲专区 | 日本在线h| 超碰在线97观看 | 婷婷综合伊人 | 久久九九久久 | www中文在线 | 在线亚洲人成电影网站色www | 激情黄色av | 日韩免费观看视频 | 亚洲专区欧美 | 免费在线成人av | 黄色的视频网站 | 精品国产区 | 亚洲 综合 专区 | 天天色天天射天天操 | 国产精品丝袜久久久久久久不卡 | 免费看的黄色小视频 | 国产日韩欧美在线观看 | 在线观看视频国产一区 | 欧美日韩在线精品 | 亚洲男模gay裸体gay | 天天操导航 | 69精品人人人人 | 91精品一区二区三区久久久久久 | 亚洲黄色免费在线 | 亚洲精品字幕在线观看 | 久久精彩免费视频 | www黄免费 | 高清av免费观看 | 91系列在线| 欧美日韩亚洲第一页 | 亚洲五月六月 | 毛片网站免费 | 99精品毛片| 亚洲经典视频 | 久久一二三四 | 一级成人免费视频 | 国产视频一区精品 | 日本aa在线 | 欧美午夜a | 日韩区视频 | 久草在线手机观看 | 国产精品一区二区在线免费观看 | 中文字幕亚洲在线观看 | 国产精品午夜久久久久久99热 | 黄色一级影院 | av在线不卡观看 | 成人sm另类专区 | 一级片观看| 亚洲精品国产综合99久久夜夜嗨 | 成人免费观看视频大全 | 日韩中文字幕免费视频 | 国产亚洲字幕 | 成人h视频在线播放 | 你操综合 | 色资源网免费观看视频 | 在线观看蜜桃视频 | 国产免费观看高清完整版 | 热re99久久精品国产66热 | 欧美日韩国产精品一区 | 91精品国产欧美一区二区 | 欧美一二三视频 | 91香蕉视频色版 | 国产成人一区二区三区久久精品 | 成在线播放 | 麻豆传媒电影在线观看 | 人人视频网站 | 国产在线观看你懂得 | 国产精品一区二区av | 69av久久| 国产一区二区综合 | 手机看片1042 | 久久久电影 | avlulu久久精品 | 色综合久久网 | 在线www色 | 免费看国产视频 | av黄色成人| 久久99这里只有精品 | 久久久亚洲电影 | 91视频传媒 | 国产99久久久精品视频 | 日韩精品中文字幕一区二区 | 三级黄免费看 | 亚洲综合导航 | 天天草天天操 | 成人一级影视 | 911免费视频 | 九九在线视频免费观看 | 在线播放亚洲 | 又黄又爽又刺激的视频 | 狠狠操天天操 | 天天操天天干天天 | 国产丝袜制服在线 | 国产视频一区二区三区在线 | 国产精品乱看 | 在线日韩中文 | 亚洲黄色区 | 月丁香婷婷 | 免费av的网站 | 缴情综合网五月天 | 亚洲婷婷丁香 | 国产99久久久精品视频 | 久久综合九色综合欧美就去吻 | 国产精品第三页 | 在线激情网 | 在线影院 国内精品 | 在线a视频免费观看 | 日韩美女黄色片 | 美女视频黄是免费的 | 最近日本中文字幕 | 日本精品久久久久久 | 波多野结衣在线视频免费观看 | 午夜精品区| 中文在线a天堂 | 久草视频在线观 | 免费一级片视频 | 亚洲精品国产欧美在线观看 | 少妇av网 | 久久久麻豆 | 国产精品久久久久久久久毛片 | 综合五月 | 国产精品毛片 | 欧美成人手机版 | 国产亚洲欧美在线视频 | 国产无遮挡又黄又爽在线观看 | 久久视频这里只有精品 | 激情五月开心 | 中文字幕电影网 | 91av视频免费在线观看 | 亚洲精品乱码久久久久 | 91在线视频在线观看 | www.五月天婷婷 | 国产亚洲片 | 337p西西人体大胆瓣开下部 | 91麻豆精品国产91久久久久 | 日本久久精品视频 | 欧洲一区二区三区精品 | 91高清在线看 | 韩日精品在线 | 成人网在线免费视频 | 综合影视 | 亚洲视频aaa| 久精品视频在线观看 | 免费在线精品视频 | 国产视频在线看 | 日韩欧美电影 | 日韩电影精品一区 | 婷婷色在线 | 日韩欧美精品一区 | 国产日产精品久久久久快鸭 | 成人网在线免费视频 | 国产va在线 | 激情五月婷婷综合网 | 在线视频 日韩 | 日本中文字幕电影在线免费观看 | 二区视频在线 | 久久久亚洲精品 | 日韩在线观看你懂的 | 精品国产一区二区在线 | 亚洲国产成人在线 | 久久成人欧美 | 一本一本久久a久久精品综合 | 不卡电影一区二区三区 | 日韩在线播放av | 国产亚洲人成网站在线观看 | 超碰个人在线 | 久久综合九色欧美综合狠狠 | 亚洲高清av在线 | 国产精品6999成人免费视频 | 亚洲精品国偷拍自产在线观看蜜桃 | 国产中的精品av小宝探花 | 色婷婷激情 | 一区二区三区免费在线观看 | 免费成人在线观看 | 黄色成人在线观看 | 中文字幕在线看视频国产 | 久久久国产日韩 | 99免费视频 | 狠狠网站 | 欧美性色xo影院 | 91精品国产一区二区三区 | 婷婷www| 欧美精品乱码99久久影院 | 黄色的网站在线 | 国产成人在线免费观看 | 国产亚洲精品久 | 免费在线看成人av | 亚洲激情国产精品 | 成人av一区二区兰花在线播放 | 欧美日韩不卡一区二区 | 久久综合九色九九 | 久久精品视频播放 | 中文字幕一二三区 | 国产精品久久久亚洲 | 精品超碰| 丝袜美女视频网站 | 国产999精品久久久久久麻豆 | 亚洲视频 视频在线 | 国产精品一区免费在线观看 | 日本精品久久久久 | 干狠狠| 狠狠色丁香婷婷综合橹88 | 麻豆一级视频 | 97视频免费看 | 国产精品久久久久久久久久久杏吧 | 精品九九久久 | 久久久久久久久久久福利 | 天天草天天爽 | 亚洲婷婷丁香 | 亚洲精品88欧美一区二区 | 欧美性粗大hdvideo | 午夜婷婷网 | 亚洲乱亚洲乱亚洲 | 婷婷激情五月综合 | 日本韩国欧美在线观看 | 久久另类视频 | 国产成人免费观看久久久 | 国产精品久久久久999 | 成年人在线观看视频免费 | 中文字幕影片免费在线观看 | 狠狠色丁香久久婷婷综合_中 | 亚洲一区二区视频在线播放 | 一区在线电影 | 99精品久久精品一区二区 | 91麻豆高清视频 | 99热国产精品 | www黄色av | 一区二区中文字幕在线观看 | 天天做天天干 | 久久久精品亚洲 | 日韩av有码在线 | 亚洲区精品视频 | 日韩电影一区二区三区在线观看 | 一区二区不卡在线观看 | 婷婷av综合 | 色久网| www.黄色片网站 | 欧美成人xxxx| 丰满少妇在线观看资源站 | 亚洲精品免费在线 | av+在线播放在线播放 | 久久看片网站 | 91禁看片 |