国产无遮挡裸体免费直播视频,久久精品国产蜜臀av,动漫在线视频一区二区,欧亚日韩一区二区三区,久艹在线 免费视频,国产精品美女网站免费,正在播放 97超级视频在线观看,斗破苍穹年番在线观看免费,51最新乱码中文字幕

Golang實(shí)現(xiàn)Java虛擬機(jī)之解析class文件詳解

 更新時(shí)間:2024年01月11日 09:18:45   作者:橡皮筋兒  
這篇文章主要為大家詳細(xì)介紹了Golang實(shí)現(xiàn)Java虛擬機(jī)之解析class文件的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

前言

所需前置知識(shí)為:JAVA語言、JVM知識(shí)

對(duì)應(yīng)項(xiàng)目:jvmgo

一、準(zhǔn)備環(huán)境

操作系統(tǒng):Windows 11

1.1 JDK版本

openjdk version "1.8.0_382"

1.2 Go版本

go version go1.21.0 windows/amd64

1.3 配置Go工作空間

1.4 java命令指示

Java虛擬機(jī)的工作是運(yùn)行Java應(yīng)用程序。和其他類型的應(yīng)用程序一樣,Java應(yīng)用程序也需要一個(gè)入口點(diǎn),這個(gè)入口點(diǎn)就是我們熟知的main()方法。最簡(jiǎn)單的Java程序是 只有一個(gè)main()方法的類,如著名的HelloWorld程序。

public class HelloWorld {
  public static void main(String[] args) {
    System.out.println("Hello, world!");
  }
}

JVM如何知道從哪個(gè)類啟動(dòng)呢,虛擬機(jī)規(guī)范并沒有明確,而是需要虛擬機(jī)實(shí)現(xiàn)。比如Oracle的JVM就是通過java命令啟動(dòng)的,主類名由命令行參數(shù)決定。

java命令有如下4種形式:

java [-options] class [args]
java [-options] -jar jarfile [args]
javaw [-options] class [args]
javaw [-options] -jar jarfile [args]

可以向java命令傳遞三組參數(shù):選項(xiàng)、主類名(或者JAR文件名) 和main()方法參數(shù)。選項(xiàng)由減號(hào)(–)開頭。通常,第一個(gè)非選項(xiàng)參數(shù) 給出主類的完全限定名(fully qualified class name)。但是如果用戶提供了–jar選項(xiàng),則第一個(gè)非選項(xiàng)參數(shù)表示JAR文件名,java命令必須從這個(gè)JAR文件中尋找主類。javaw命令和java命令幾乎一樣,唯 一的差別在于,javaw命令不顯示命令行窗口,因此特別適合用于啟 動(dòng)GUI(圖形用戶界面)應(yīng)用程序。

選項(xiàng)可以分為兩類:標(biāo)準(zhǔn)選項(xiàng)和非標(biāo)準(zhǔn)選項(xiàng)。標(biāo)準(zhǔn)選項(xiàng)比較穩(wěn)定,不會(huì)輕易變動(dòng)。非標(biāo)準(zhǔn)選項(xiàng)以-X開頭,

選項(xiàng)用途
-version輸出版本信息,然后退出
-? / -help輸出幫助信息,然后退出
-cp / -classpath指定用戶類路徑
-Dproperty=value設(shè)置Java系統(tǒng)屬性
-Xms<size>設(shè)置初始堆空間大小
-Xmx<size>設(shè)置最大堆空間大小
-Xss<size>設(shè)置線程??臻g大小

二、編寫命令行工具

環(huán)境準(zhǔn)備完畢,接下來實(shí)現(xiàn)java命令的的第一種用法。

2.1 創(chuàng)建目錄

創(chuàng)建cmd.go

Go源文件一般以.go作為后綴,文件名全部小寫,多個(gè)單詞之間使用下劃線分隔。Go語言規(guī)范要求Go源文件必須使用UTF-8編碼,詳見https://golang.org/ref/spec

2.2 結(jié)構(gòu)體存儲(chǔ)cmd選項(xiàng)

在文件中定義cmd中java命令需要的選項(xiàng)和參數(shù)

package ch01

// author:郜宇博
type Cmd struct {
	// 標(biāo)注是否為 --help
	helpFlag bool
	//標(biāo)注是否為 --version
	versionFlag bool
	//選項(xiàng)
	cpOption string
	//主類名,或者是jar文件
	class string
	//參數(shù)
	args []string
}

Go語言標(biāo)準(zhǔn)庫包

由于要處理的命令行,因此將使用到flag()函數(shù),此函數(shù)為Go的標(biāo)準(zhǔn)庫包之一。

Go語言的標(biāo)準(zhǔn)庫以包的方式提供支持,下表列出了Go語言標(biāo)準(zhǔn)庫中常見的包及其功能。

Go語言標(biāo)準(zhǔn)庫包名功 能
bufio帶緩沖的 I/O 操作
bytes實(shí)現(xiàn)字節(jié)操作
container封裝堆、列表和環(huán)形列表等容器
crypto加密算法
database數(shù)據(jù)庫驅(qū)動(dòng)和接口
debug各種調(diào)試文件格式訪問及調(diào)試功能
encoding常見算法如 JSON、XML、Base64 等
flag命令行解析
fmt格式化操作
goGo語言的詞法、語法樹、類型等??赏ㄟ^這個(gè)包進(jìn)行代碼信息提取和修改
htmlHTML 轉(zhuǎn)義及模板系統(tǒng)
image常見圖形格式的訪問及生成
io實(shí)現(xiàn) I/O 原始訪問接口及訪問封裝
math數(shù)學(xué)庫
net網(wǎng)絡(luò)庫,支持 Socket、HTTP、郵件、RPC、SMTP 等
os操作系統(tǒng)平臺(tái)不依賴平臺(tái)操作封裝
path兼容各操作系統(tǒng)的路徑操作實(shí)用函數(shù)
pluginGo 1.7 加入的插件系統(tǒng)。支持將代碼編譯為插件,按需加載
reflect語言反射支持??梢詣?dòng)態(tài)獲得代碼中的類型信息,獲取和修改變量的值
regexp正則表達(dá)式封裝
runtime運(yùn)行時(shí)接口
sort排序接口
strings字符串轉(zhuǎn)換、解析及實(shí)用函數(shù)
time時(shí)間接口
text文本模板及 Token 詞法器

flag()函數(shù)

[]: https://studygolang.com/pkgdoc

eg:flag.TypeVar()

基本格式如下: flag.TypeVar(Type指針, flag名, 默認(rèn)值, 幫助信息) 例如我們要定義姓名、年齡、婚否三個(gè)命令行參數(shù),我們可以按如下方式定義:

var name string
var age int
var married bool
var delay time.Duration
flag.StringVar(&name, "name", "張三", "姓名")
flag.IntVar(&age, "age", 18, "年齡")
flag.BoolVar(&married, "married", false, "婚否")
flag.DurationVar(&delay, "d", 0, "時(shí)間間隔")

2.3 接收處理用戶輸入的命令行指令

創(chuàng)建parseCmd()函數(shù),實(shí)現(xiàn)接受處理用戶輸入的命令行指令

func parseCmd() *Cmd {
	cmd := &Cmd{}

	flag.Usage = printUsage
	flag.BoolVar(&cmd.helpFlag, "help", false, "print help message")
	flag.BoolVar(&cmd.helpFlag, "?", false, "print help message")
	flag.BoolVar(&cmd.versionFlag, "version", false, "print version and exit")
	flag.StringVar(&cmd.cpOption, "classpath", "", "classpath")
	flag.StringVar(&cmd.cpOption, "cp", "", "classpath")
	flag.Parse()

	args := flag.Args()
	if len(args) > 0 {
		cmd.class = args[0]
		cmd.args = args[1:]
	}

	return cmd
}

func printUsage() {
	fmt.Printf("Usage: %s [-options] class [args...]\n", os.Args[0])
	//flag.PrintDefaults()
}

首先設(shè)置flag.Usage變量,把printUsage()函數(shù)賦值給它;

然后調(diào) 用flag包提供的各種Var函數(shù)設(shè)置需要解析的選項(xiàng);

接著調(diào)用 Parse()函數(shù)解析選項(xiàng)。

如果Parse()函數(shù)解析失敗,它就調(diào)用printUsage()函數(shù)把命令的用法打印到控制臺(tái)。

如果解析成功,調(diào)用flag.Args()函數(shù)可以捕獲其他沒有被解析 的參數(shù)。其中第一個(gè)參數(shù)就是主類名,剩下的是要傳遞給主類的參數(shù)。

2.4 測(cè)試

與cmd.go文件一樣,main.go文件的包名也是main。在Go 語言中,main是一個(gè)特殊的包,這個(gè)包所在的目錄(可以叫作任何 名字)會(huì)被編譯為可執(zhí)行文件。Go程序的入口也是main()函數(shù),但 是不接收任何參數(shù),也不能有返回值。

測(cè)試代碼如下:

package main

import "fmt"

func main() {
	cmd := parseCmd()
	if cmd.versionFlag {
		//模擬輸出版本
		fmt.Println("version 0.0.1")
	} else if cmd.helpFlag || cmd.class == "" {
		printUsage()
	} else {
		startJVM(cmd)
	}
}

// 模擬啟動(dòng)JVM
func startJVM(cmd *Cmd) {
	fmt.Printf("classpath:%s class:%s args:%v\n",
		cmd.cpOption, cmd.class, cmd.args)
}

main()函數(shù)先調(diào)用ParseCommand()函數(shù)解析命令行參數(shù),如 果一切正常,則調(diào)用startJVM()函數(shù)啟動(dòng)Java虛擬機(jī)。如果解析出現(xiàn)錯(cuò)誤,或者用戶輸入了-help選項(xiàng),則調(diào)用PrintUsage()函數(shù)打印出幫助信息。如果用戶輸入了-version選項(xiàng),則輸版本信息。因?yàn)槲覀冞€沒有真正開始編寫Java虛擬機(jī),所以startJVM()函數(shù)暫時(shí)只是打印一些信息而已。

在終端:

go install jvmgo\ch0

此時(shí)在工作空間的bin目錄中會(huì)生成ch01.exe的文件,運(yùn)行:結(jié)果如下

三、獲取類路徑

已經(jīng)完成了JAVA應(yīng)用程序如何啟動(dòng):命令行啟動(dòng),并獲取到了啟動(dòng)時(shí)需要的選項(xiàng)和參數(shù)。

但是,如果要啟動(dòng)一個(gè)最簡(jiǎn)單的“Hello World”程序(如下),也需要加載很多所需的類進(jìn)入JVM

public class HelloWorld {
  public static void main(String[] args) {
    System.out.println("Hello, world!");
  }
}

加載HelloWorld類之前,需要加載該類的父類(超類),也就是java.lang.Object,main函數(shù)的參數(shù)為String[]類型,因此也需要將java.lang.String類和java.lang.String[]加載,輸出字符串又需要加載java.lang.System類,等等。接下來就來解決如何獲取這些類的路徑。

3.1類路徑介紹

Java虛擬機(jī)規(guī)范并沒有規(guī)定虛擬機(jī)應(yīng)該從哪里尋找類,因此不同的虛擬機(jī)實(shí)現(xiàn)可以采用不同的方法。

Oracle的Java虛擬機(jī)實(shí)現(xiàn)根據(jù)類路徑(class path)來搜索類。

按照搜索的先后順序,類路徑可以 分為以下3個(gè)部分:

  • 啟動(dòng)類路徑(bootstrap classpath)
  • 擴(kuò)展類路徑(extension classpath)
  • 用戶類路徑(user classpath)

啟動(dòng)類路徑默認(rèn)對(duì)應(yīng)jre\lib目錄,Java標(biāo)準(zhǔn)庫(大部分在rt.jar里) 位于該路徑。

擴(kuò)展類路徑默認(rèn)對(duì)應(yīng)jre\lib\ext目錄,使用Java擴(kuò)展機(jī)制的類位于這個(gè)路徑。

用戶類路徑為自己實(shí)現(xiàn)的類,以及第三方類庫的路徑??梢酝ㄟ^-Xbootclasspath選項(xiàng)修改啟動(dòng)類路徑,不過一般不需要這樣做。

用戶類路徑的默認(rèn)值是當(dāng)前目錄,也就是. 。可以設(shè)置 CLASSPATH環(huán)境變量來修改用戶類路徑,但是這樣做不夠靈活,所以不推薦使用。

更好的辦法是給java命令傳遞-classpath(或簡(jiǎn)寫為-cp)選項(xiàng)。-classpath/-cp選項(xiàng)的優(yōu)先級(jí)更高,可以覆蓋CLASSPATH環(huán)境變量設(shè)置。如下:

java -cp path\to\classes ...
java -cp path\to\lib1.jar ...
java -cp path\to\lib2.zip ...

3.2解析用戶類路徑

該功能建立在命令行工具上,因此復(fù)制上次的代碼,并創(chuàng)建classpath子目錄。

Java虛擬機(jī)將使用JDK的啟動(dòng)類路徑來尋找和加載Java 標(biāo)準(zhǔn)庫中的類,因此需要某種方式指定jre目錄的位置。

命令行選項(xiàng)可以獲取,所以增加一個(gè)非標(biāo)準(zhǔn)選項(xiàng)-Xjre。

修改Cmd結(jié)構(gòu)體,添加XjreOption字段;parseCmd()函數(shù)也要相應(yīng)修改:

type Cmd struct {
	// 標(biāo)注是否為 --help
	helpFlag bool
	//標(biāo)注是否為 --version
	versionFlag bool
	//選項(xiàng)
	cpOption string
	//主類名,或者是jar文件
	class string
	//參數(shù)
	args []string
	// jre路徑
	XjreOption string
}

func parseCmd() *Cmd {
	cmd := &Cmd{}

	flag.Usage = printUsage
	flag.BoolVar(&cmd.helpFlag, "help", false, "print help message")
	flag.BoolVar(&cmd.helpFlag, "?", false, "print help message")
	flag.BoolVar(&cmd.versionFlag, "version", false, "print version and exit")
	flag.StringVar(&cmd.cpOption, "classpath", "", "classpath")
	flag.StringVar(&cmd.cpOption, "cp", "", "classpath")
	flag.StringVar(&cmd.XjreOption, "Xjre", "", "path to jre")
	flag.Parse()

	args := flag.Args()
	if len(args) > 0 {
		//第一個(gè)參數(shù)是主類名
		cmd.class = args[0]
		cmd.args = args[1:]
	}

	return cmd
}

3.3獲取用戶類路徑

可以把類路徑想象成一個(gè)大的整體,它由啟動(dòng)類路徑、擴(kuò)展類路徑和用戶類路徑三個(gè)小路徑構(gòu)成。

三個(gè)小路徑又分別由更小的路徑構(gòu)成。是不是很像組合模式(composite pattern)

接下來將使用組合模式來設(shè)計(jì)和實(shí)現(xiàn)類路徑。

1.Entry接口

定義一個(gè)Entry接口,作為所有類的基準(zhǔn)。

package classpath

import "os"

// :(linux/unix) or ;(windows)
const pathListSeparator = string(os.PathListSeparator)

type Entry interface {
    // className: fully/qualified/ClassName.class
    readClass(classpath string) ([]byte, Entry, error)
    String() string
}

常量pathListSeparator是string類型,存放路徑分隔符,后面會(huì)用到。

Entry接口中有個(gè)兩方法。

readClass()方法:負(fù)責(zé)尋找和加載class 文件。

參數(shù)是class文件的相對(duì)路徑,路徑之間用斜線/分隔,文件名有.class后綴。比如要讀取java.lang.Object類,傳 入的參數(shù)應(yīng)該是java/lang/Object.class。返回值是讀取到的字節(jié)數(shù)據(jù)、最終定位到class文件的Entry,以及錯(cuò)誤信息。

String()方法:作用相當(dāng)于Java中的toString(),用于返回變量 的字符串表示。

Go的函數(shù)或方法允許返回多個(gè)值,按照慣例,可以使用最后一個(gè)返回值作為錯(cuò)誤信息。

還需要一個(gè)類似于JAVA構(gòu)造函數(shù)的函數(shù),但在Go語言中沒有構(gòu)造函數(shù)的概念,對(duì)象的創(chuàng)建通常交由一個(gè)全局的創(chuàng)建函數(shù)來完成,以NewXXX來命令,表示"構(gòu)造函數(shù)"

newEntry()函數(shù)根據(jù)參數(shù)創(chuàng)建不同類型的Entry實(shí)例,代碼如下:

func newEntry(path string) Entry {
	////如果路徑包含分隔符 表示有多個(gè)文件 
	if strings.Contains(path, pathListSeparator) {
		return newCompositeEntry(path)
	}
	//包含*,則說明要將相應(yīng)目錄下的所有class文件加載
	if strings.HasSuffix(path, "*") {
		return newWildcardEntry(path)
	}
	//包含.jar,則說明是jar文件,通過zip方式加載
	if strings.HasSuffix(path, ".jar") || strings.HasSuffix(path, ".JAR") ||
		strings.HasSuffix(path, ".zip") || strings.HasSuffix(path, ".ZIP") {

		return newZipEntry(path)
	}

	return newDirEntry(path)
}

2.實(shí)現(xiàn)類

存在四種類路徑指定方式:

  • 普通路徑形式:gyb/gyb
  • jar/zip形式:/gyb/gyb.jar
  • 通配符形式:gyb/*
  • 多個(gè)路徑形式:gyb/1:/gyb/2

DirEntry(普通形式)

創(chuàng)建entry_dir.go,定義DirEntry結(jié)構(gòu)體:

package classpath

import "io/ioutil"
import "path/filepath"

type DirEntry struct {
	absDir string
}

func newDirEntry(path string) *DirEntry {
	//轉(zhuǎn)化為絕對(duì)路徑
	absDir, err := filepath.Abs(path)
	if err != nil {
		panic(err)
	}
	return &DirEntry{absDir}
}

func (self *DirEntry) readClass(className string) ([]byte, Entry, error) {
	//拼接類文件目錄 和 類文件名  
	// '/gyb/xxx/' + 'helloworld.class' = '/gyb/xxx/helloworld.class'
	fileName := filepath.Join(self.absDir, className)
	data, err := ioutil.ReadFile(fileName)
	return data, self, err
}

func (self *DirEntry) String() string {
	return self.absDir
}

DirEntry只有一個(gè)字段,用于存放目錄的絕對(duì)路徑。

和Java語言不同,Go結(jié)構(gòu)體不需要顯示實(shí)現(xiàn)接口,只要方法匹配即可。

ZipEntry(jar/zip形式)

package classpath

import "archive/zip"
import "errors"
import "io/ioutil"
import "path/filepath"

type ZipEntry struct {
	absPath string
}

func newZipEntry(path string) *ZipEntry {
	absPath, err := filepath.Abs(path)
	if err != nil {
		panic(err)
	}
	return &ZipEntry{absPath}
}

func (self *ZipEntry) readClass(className string) ([]byte, Entry, error) {
	r, err := zip.OpenReader(self.absPath)
	if err != nil {
		return nil, nil, err
	}

	defer r.Close()
	for _, f := range r.File {
		if f.Name == className {
			rc, err := f.Open()
			if err != nil {
				return nil, nil, err
			}

			defer rc.Close()
			data, err := ioutil.ReadAll(rc)
			if err != nil {
				return nil, nil, err
			}

			return data, self, nil
		}
	}

	return nil, nil, errors.New("class not found: " + className)
}

func (self *ZipEntry) String() string {
	return self.absPath
}

首先打開ZIP文件,如果這一步出錯(cuò)的話,直接返回。然后遍歷 ZIP壓縮包里的文件,看能否找到class文件。如果能找到,則打開 class文件,把內(nèi)容讀取出來,并返回。如果找不到,或者出現(xiàn)其他錯(cuò) 誤,則返回錯(cuò)誤信息。有兩處使用了defer語句來確保打開的文件得 以關(guān)閉。

CompositeEntry(多路徑形式)

CompositeEntry由更小的Entry組成,正好可以表示成[]Entry。

在Go語言中,數(shù)組屬于比較低層的數(shù)據(jù)結(jié)構(gòu),很少直接使用。大部分情況下,使用更便利的slice類型。

構(gòu)造函數(shù)把參數(shù)(路徑列表)按分隔符分成小路徑,然后把每個(gè)小路徑都轉(zhuǎn)換成具體的 Entry實(shí)例。

package classpath

import "errors"
import "strings"

type CompositeEntry []Entry

func newCompositeEntry(pathList string) CompositeEntry {
	compositeEntry := []Entry{}

	for _, path := range strings.Split(pathList, pathListSeparator) {
		//去判斷 path 屬于哪其他三種哪一種情況 生成對(duì)應(yīng)的 ClassDirEntry類目錄對(duì)象
		entry := newEntry(path)
		compositeEntry = append(compositeEntry, entry)
	}

	return compositeEntry
}

func (self CompositeEntry) readClass(className string) ([]byte, Entry, error) {
	//遍歷切片 中的 類目錄對(duì)象
	for _, entry := range self {
		//如果找到了 對(duì)應(yīng)的 類 直接返回
		data, from, err := entry.readClass(className)
		if err == nil {
			return data, from, nil
		}

	}
	//沒找到 返回錯(cuò)誤
	return nil, nil, errors.New("class not found: " + className)
}

func (self CompositeEntry) String() string {
	strs := make([]string, len(self))

	for i, entry := range self {
		strs[i] = entry.String()
	}

	return strings.Join(strs, pathListSeparator)
}

WildcardEntry(通配符形式)

WildcardEntry實(shí)際上也是CompositeEntry,所以就不再定義新的類型了。

首先把路徑末尾的星號(hào)去掉,得到baseDir,然后調(diào)用filepath包的Walk()函數(shù)遍歷baseDir創(chuàng)建ZipEntry。Walk()函數(shù)的第二個(gè)參數(shù) 也是一個(gè)函數(shù)。

walkFn中,根據(jù)后綴名選出JAR文件,并且返回SkipDir跳過子目錄(通配符類路徑不能遞歸匹配子目錄下的JAR文件)。

package classpath

import "os"
import "path/filepath"
import "strings"

func newWildcardEntry(path string) CompositeEntry {
	//截取通用匹配符 /gyb/* 截取掉 *
	baseDir := path[:len(path)-1] // remove *
	//多個(gè) 類目錄對(duì)象
	compositeEntry := []Entry{}

	walkFn := func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		//如果為空
		if info.IsDir() && path != baseDir {
			return filepath.SkipDir
		}
		//如果是 .jar  或者 .JAR 結(jié)尾的文件
		if strings.HasSuffix(path, ".jar") || strings.HasSuffix(path, ".JAR") {
			jarEntry := newZipEntry(path)
			compositeEntry = append(compositeEntry, jarEntry)
		}
		return nil
	}
	//遍歷 目錄下所有 .jar .JAR 文件 生成ZipEntry目錄對(duì)象 放在切片中返回
	//walFn為函數(shù)
	filepath.Walk(baseDir, walkFn)

	return compositeEntry
}

3.4實(shí)現(xiàn)類目錄

前面提到了java 虛擬機(jī)默認(rèn) 會(huì)先從啟動(dòng)路徑--->擴(kuò)展類路徑 --->用戶類路徑

按順序依次去尋找,加載類。

那么就會(huì)有3個(gè)類目錄對(duì)象,所以就要定義一個(gè)結(jié)構(gòu)體去存放它。

type Classpath struct {
	BootClasspath Entry
	ExtClasspath  Entry
	UserClasspath Entry
}

啟動(dòng)類路徑

啟動(dòng)路徑,其實(shí)對(duì)應(yīng)Jre目錄下``lib` 也就是運(yùn)行java 程序必須可少的基本運(yùn)行庫。

通過 -Xjre 指定 如果不指定 會(huì)在當(dāng)前路徑下尋找jre 如果找不到 就會(huì)從我們?cè)谘bjava是配置的JAVA_HOME環(huán)境變量 中去尋找。

所以獲取驗(yàn)證環(huán)境變量的方法如下:

func getJreDir(jreOption string) string {
	//如果 從cmd  -Xjre 獲取到目錄 并且存在
	if jreOption != "" && exists(jreOption) {
	//返回目錄
		return jreOption 
	}
	//如果 當(dāng)前路徑下 有 jre 返回目錄
	if exists("./jre") { 
		return "./jre"
	}
	//如果 上面都找不到 到系統(tǒng)環(huán)境 變量中尋找 
	if jh := os.Getenv("JAVA_HOME"); jh != "" {
		//存在 就返回
		return filepath.Join(jh, "jre") 
	}
	//都找不到 就報(bào)錯(cuò)
	panic("Can not find jre folder!") 
}
//判斷 目錄是否存在
func exists(path string) bool {
	if _, err := os.Stat(path); err != nil {
	if os.IsNotExist(err) { return false
} }
return true }

擴(kuò)展類路徑

擴(kuò)展類 路徑一般 在啟動(dòng)路徑 的子目錄下jre/lib/ext

func (self *Classpath) parseBootAndExtClasspath(jreOption string) {
	jreDir := getJreDir(jreOption)

	// 拼接成jre 的路徑
	// jre/lib/*
	jreLibPath := filepath.Join(jreDir, "lib", "*")
	//加載 所有底下的 jar包
	self.BootClasspath = newWildcardEntry(jreLibPath)

	// 拼接 擴(kuò)展類 的路徑
	// jre/lib/ext/*
	jreExtPath := filepath.Join(jreDir, "lib", "ext", "*")
	//加載 所有底下的jar包
	self.ExtClasspath = newWildcardEntry(jreExtPath)
}

用戶類路徑

用戶類路徑通過前面提到的 -classpath 來指定 ,如果沒有指定 就默認(rèn)為當(dāng)前路徑就好

func (self *Classpath) parseUserClasspath(cpOption string) {
	//如果沒有指定
	if cpOption == "" {
	// . 作為當(dāng)前路徑
	cpOption = "." 
	}
	//創(chuàng)建 類目錄對(duì)象
	self.UserClasspath = newEntry(cpOption)
}

實(shí)現(xiàn)類的加載

對(duì)于指定文件類名取查找 我們是按前面提到的(啟動(dòng)路徑--->擴(kuò)展類路徑 --->用戶類路徑
按順序依次去尋找,加載類),沒找到就挨個(gè)查找下去。

如果用戶沒有提供-classpath/-cp選項(xiàng),則使用當(dāng)前目錄作為用 戶類路徑。ReadClass()方法依次從啟動(dòng)類路徑、擴(kuò)展類路徑和用戶 類路徑中搜索class文件,

//根據(jù)類名 分別從 bootClasspath,extClasspath,userClasspath 依次加載類目錄
func (self *Classpath) ReadClass(className string) ([]byte, ClassDirEntry, error) {
	className = className + ".class"
	if data, entry, err := self.BootClasspath.readClass(className); err == nil{ return data, entry, err }
	if data, entry, err := self.ExtClasspath.readClass(className); err == nil { return data, entry, err }
	return self.UserClasspath.readClass(className)
}

初始化類加載目錄

定義一個(gè)初始化函數(shù),來作為初始函數(shù),執(zhí)行后生成一個(gè) Classpath對(duì)象。

//jreOption 為啟動(dòng)類目錄  cpOption 為 用戶指定類目錄 從cmd 命令行 中解析獲取
func InitClassPath(jreOption, cpOption string) *Classpath {
	cp := &Classpath{}
	//初始化 啟動(dòng)類目錄
	cp.parseBootAndExtClasspath(jreOption)
	//初始化 用戶類目錄
	cp.parseUserClasspath(cpOption)
	return cp
}

注意,傳遞給ReadClass()方法的類名不包含“.class”后綴。

3.5總結(jié)

3.6測(cè)試

成功獲取到class文件!

四、解析Class文件

4.1 class文件介紹

詳細(xì)class文件分析

作為類/接口信息的載體,每一個(gè)class文件都完整的定義了一個(gè)類,為了使Java程序可以實(shí)現(xiàn)“編寫一次,處處運(yùn)行”,java虛擬機(jī)對(duì)class文件的格式進(jìn)行了嚴(yán)格的規(guī)范。

但是對(duì)于從哪里加載class文件,給予了高度自由空間:第三節(jié)中說過,可以從文件系統(tǒng)讀取jar/zip文件中的class文件,除此之外,也可以從網(wǎng)絡(luò)下載,甚至是直接在運(yùn)行中生成class文件。

構(gòu)成class文件的基本數(shù)據(jù)單位是字節(jié),可以把整個(gè)class文件當(dāng) 成一個(gè)字節(jié)流來處理。稍大一些的數(shù)據(jù)由連續(xù)多個(gè)字節(jié)構(gòu)成,這些數(shù)據(jù)在class文件中以大端(big-endian)方式存儲(chǔ)。

為了描述class文件格式,Java虛擬機(jī)規(guī)范定義了u1、u2u4三種數(shù)據(jù)類型來表示1、 2和4字節(jié)無符號(hào)整數(shù),分別對(duì)應(yīng)Go語言的uint8、uint16uint32類型。

相同類型的多條數(shù)據(jù)一般按表(table)的形式存儲(chǔ)在class文件中。表由表頭表項(xiàng)(item)構(gòu)成,表頭是u2或u4整數(shù)。假設(shè)表頭是 n,后面就緊跟著n個(gè)表項(xiàng)數(shù)據(jù)。

Java虛擬機(jī)規(guī)范使用一種類似C語言的結(jié)構(gòu)體語法來描述class 文件格式。整個(gè)class文件被描述為一個(gè)ClassFile結(jié)構(gòu),代碼如下:

ClassFile {
    u4 magic;
    u2 minor_version;
    u2 major_version;
    u2 constant_pool_count;
    cp_info constant_pool[constant_pool_count-1];
    u2 access_flags;
    u2 this_class;
    u2 super_class;
    u2 interfaces_count;
    u2 interfaces[interfaces_count];
    u2 fields_count;
    field_info fields[fields_count];
    u2 methods_count;
    method_info methods[methods_count];
    u2 attributes_count;
    attribute_info attributes[attributes_count];
}

!表示大小不定。

4.2解析class文件

Go語言內(nèi)置了豐富的數(shù)據(jù)類型,非常適合處理class文件。

如下為Go和Java語言基本數(shù)據(jù)類型對(duì)照關(guān)系:

Go語言類型Java語言類型說明
int8byte8比特有符號(hào)整數(shù)
uint8(別名byte)N/A8比特?zé)o符號(hào)整數(shù)
int16short16比特有符號(hào)整數(shù)
uint16char16比特?zé)o符號(hào)整數(shù)
int32(別名rune)int32比特有符號(hào)整數(shù)
uint32N/A32比特?zé)o符號(hào)整數(shù)
int64long64比特有符號(hào)整數(shù)
uint64N/A64比特?zé)o符號(hào)整數(shù)
float32float32比特IEEE-754浮點(diǎn)數(shù)
float64double64比特IEEE-754浮點(diǎn)數(shù)

4.2.1讀取數(shù)據(jù)

解析class文件的第一步是從里面讀取數(shù)據(jù)。雖然可以把class文件當(dāng)成字節(jié)流來處理,但是直接操作字節(jié)很不方便,所以先定義一個(gè)結(jié)構(gòu)體ClassReader來幫助讀取數(shù)據(jù),創(chuàng)建class_reader.go。

package classfile
import "encoding/binary"
type ClassReader struct {
	data []byte
}
func (self *ClassReader) readUint8() uint8 {...} // u1
func (self *ClassReader) readUint16() uint16 {...} // u2
func (self *ClassReader) readUint32() uint32 {...} // u4
func (self *ClassReader) readUint64() uint64 {...}
func (self *ClassReader) readUint16s() []uint16 {...}
func (self *ClassReader) readBytes(length uint32) []byte {...}

ClassReader只是[]byte類型的包裝而已。readUint8()讀取u1類型數(shù)據(jù)。

ClassReader并沒有使用索引記錄數(shù)據(jù)位置,而是使用Go 語言的reslice語法跳過已經(jīng)讀取的數(shù)據(jù)

實(shí)現(xiàn)代碼如下:

// u1
func (self *ClassReader) readUint8() uint8 {
    val := self.data[0]
    self.data = self.data[1:]
    return val
}

// u2
func (self *ClassReader) readUint16() uint16 {
    val := binary.BigEndian.Uint16(self.data)
    self.data = self.data[2:]
    return val
}

// u4
func (self *ClassReader) readUint32() uint32 {
    val := binary.BigEndian.Uint32(self.data)
    self.data = self.data[4:]
    return val
}

func (self *ClassReader) readUint64() uint64 {
    val := binary.BigEndian.Uint64(self.data)
    self.data = self.data[8:]
    return val
}

func (self *ClassReader) readUint16s() []uint16 {
    n := self.readUint16()
    s := make([]uint16, n)
    for i := range s {
       s[i] = self.readUint16()
    }
    return s
}

func (self *ClassReader) readBytes(n uint32) []byte {
    bytes := self.data[:n]
    self.data = self.data[n:]
    return bytes
}

Go標(biāo)準(zhǔn)庫encoding/binary包中定義了一個(gè)變量BigEndian,可以從[]byte中解碼多字節(jié)數(shù)據(jù)。

4.2.2解析整體結(jié)構(gòu)

有了ClassReader,可以開始解析class文件了。創(chuàng)建class_file.go文件,在其中定義ClassFile結(jié)構(gòu)體,與4.1中的class文件中字段對(duì)應(yīng)。

package classfile
import "fmt"

type ClassFile struct {
    //magic uint32
    minorVersion uint16
    majorVersion uint16
    constantPool ConstantPool
    accessFlags uint16
    thisClass uint16
    superClass uint16
    interfaces []uint16
    fields []*MemberInfo
    methods []*MemberInfo
    attributes []AttributeInfo
}

在class_file.go文件中實(shí)現(xiàn)一系列函數(shù)和方法。

func Parse(classData []byte) (cf *ClassFile, err error) {...}
func (self *ClassFile) read(reader *ClassReader) {...}
func (self *ClassFile) readAndCheckMagic(reader *ClassReader) {...}
func (self *ClassFile) readAndCheckVersion(reader *ClassReader) {...}
func (self *ClassFile) MinorVersion() uint16 {...} // getter
func (self *ClassFile) MajorVersion() uint16 {...} // getter
func (self *ClassFile) ConstantPool() ConstantPool {...} // getter
func (self *ClassFile) AccessFlags() uint16 {...} // getter
func (self *ClassFile) Fields() []*MemberInfo {...} // getter
func (self *ClassFile) Methods() []*MemberInfo {...} // getter
func (self *ClassFile) ClassName() string {...}
func (self *ClassFile) SuperClassName() string {...}
func (self *ClassFile) InterfaceNames() []string {...}

相比Java語言,Go的訪問控制非常簡(jiǎn)單:只有公開和私有兩種。

所有首字母大寫的類型、結(jié)構(gòu)體、字段、變量、函數(shù)、方法等都是公開的,可供其他包使用。
首字母小寫則是私有的,只能在包內(nèi)部使用。

解析[]byte

Parse()函數(shù)把[]byte解析成ClassFile結(jié)構(gòu)體。

func Parse(classData []byte) (cf *ClassFile, err error) {
    defer func() {
       //嘗試捕獲 panic,并將其存儲(chǔ)在變量 r 中。如果沒有發(fā)生 panic,r 將為 nil。
       if r := recover(); r != nil {
          var ok bool
          //判斷 r 是否是一個(gè) error 類型
          err, ok = r.(error)
          if !ok {
             err = fmt.Errorf("%v", r)
          }
       }
    }()

    cr := &ClassReader{classData}
    cf = &ClassFile{}
    cf.read(cr)
    return
}

順序解析

read() 方法依次調(diào)用其他方法解析class文件,順序一定要保證正確,與class文件相對(duì)應(yīng)。

func (self *ClassFile) read(reader *ClassReader) {
  	//讀取并檢查類文件的魔數(shù)。 
    self.readAndCheckMagic(reader)
	//讀取并檢查類文件的版本號(hào)。
    self.readAndCheckVersion(reader)
    //解析常量池,常量池類還沒寫
    self.constantPool = readConstantPool(reader)
    //讀取類的訪問標(biāo)志
    self.accessFlags = reader.readUint16()
    //讀取指向當(dāng)前類在常量池中的索引
    self.thisClass = reader.readUint16()
    //父類在常量池中的索引
    self.superClass = reader.readUint16()
    //讀取接口表的數(shù)據(jù)
    self.interfaces = reader.readUint16s()
    //讀取類的字段信息
    self.fields = readMembers(reader, self.constantPool)
    //讀取類的方法信息
    self.methods = readMembers(reader, self.constantPool)
    //讀取類的屬性信息(類級(jí)別的注解、源碼文件等)
    self.attributes = readAttributes(reader, self.constantPool)
}
  • self.readAndCheckMagic(reader): 這是一個(gè) ClassFile 結(jié)構(gòu)的方法,用于讀取并檢查類文件的魔數(shù)。魔數(shù)是類文件的標(biāo)識(shí)符,用于確定文件是否為有效的類文件。
  • self.readAndCheckVersion(reader): 這個(gè)方法用于讀取并檢查類文件的版本號(hào)。Java類文件具有版本號(hào),標(biāo)識(shí)了它們的Java編譯器版本。這里會(huì)對(duì)版本號(hào)進(jìn)行檢查。
  • self.constantPool = readConstantPool(reader): 這一行代碼調(diào)用 readConstantPool 函數(shù)來讀取常量池部分的數(shù)據(jù),并將其存儲(chǔ)在 ClassFile 結(jié)構(gòu)的 constantPool 字段中。常量池是一個(gè)包含各種常量信息的表格,用于支持類文件中的各種符號(hào)引用。
  • self.accessFlags = reader.readUint16(): 這一行代碼讀取類的訪問標(biāo)志,它標(biāo)識(shí)類的訪問權(quán)限,例如 public、private 等。
  • self.thisClass = reader.readUint16(): 這行代碼讀取指向當(dāng)前類在常量池中的索引,表示當(dāng)前類的類名。
  • self.superClass = reader.readUint16(): 這行代碼讀取指向父類在常量池中的索引,表示當(dāng)前類的父類名。
  • self.interfaces = reader.readUint16s(): 這行代碼讀取接口表的數(shù)據(jù),表示當(dāng)前類實(shí)現(xiàn)的接口。
  • self.fields = readMembers(reader, self.constantPool): 這行代碼調(diào)用 readMembers 函數(shù),以讀取類的字段信息,并將它們存儲(chǔ)在 fields 字段中。字段包括類的成員變量。
  • self.methods = readMembers(reader, self.constantPool): 這行代碼類似于上一行,但它讀取類的方法信息,并將它們存儲(chǔ)在 methods 字段中。
  • self.attributes = readAttributes(reader, self.constantPool): 最后,這行代碼調(diào)用 readAttributes 函數(shù),以讀取類的屬性信息,并將它們存儲(chǔ)在 attributes 字段中。屬性包括類級(jí)別的注解、源碼文件等信息。

以下均為類似于Java的getter方法,以后將不再贅述。

func (self *ClassFile) MinorVersion() uint16 {
	return self.minorVersion
}
func (self *ClassFile) MajorVersion() uint16 {
	return self.majorVersion
}
func (self *ClassFile) ConstantPool() ConstantPool {
	return self.constantPool
}
func (self *ClassFile) AccessFlags() uint16 {
	return self.accessFlags
}
func (self *ClassFile) Fields() []*MemberInfo {
	return self.fields
}
func (self *ClassFile) Methods() []*MemberInfo {
	return self.methods
}

ClassName從常量池中獲取,SuperClassName同理,常量池還未實(shí)現(xiàn)。

所有類的超類(父類),Object是java中唯一沒有父類的類,一個(gè)類可以不是Object的直接子類,但一定是繼承于Object并拓展于Object。

func (self *ClassFile) ClassName() string {
    return self.constantPool.getClassName(self.thisClass)
}
func (self *ClassFile) SuperClassName() string {
	if self.superClass > 0 {
		return self.constantPool.getClassName(self.superClass)
	}
    //Object類
	return ""
}

Java的類是單繼承,多實(shí)現(xiàn)的,因此獲取接口應(yīng)該使用循環(huán),也從常量池中獲取。

func (self *ClassFile) InterfaceNames() []string {
    interfaceNames := make([]string, len(self.interfaces))
    for i, cpIndex := range self.interfaces {
       interfaceNames[i] = self.constantPool.getClassName(cpIndex)
    }
    return interfaceNames
}

解析魔數(shù)

很多文件格式都會(huì)規(guī)定滿足該格式的文件必須以某幾個(gè)固定字節(jié)開頭,這幾個(gè)字節(jié)主要起標(biāo)識(shí)作用,叫作魔數(shù)(magic number)。

  • PDF文件以4字節(jié)“%PDF”(0x25、0x50、0x44、0x46)開頭
  • ZIP 文件以2字節(jié)“PK”(0x50、0x4B)開頭
  • class文件的魔數(shù) 是“0xCAFEBABE” 。

因此readAndCheckMagic()方法的代碼如下。

func (self *ClassFile) readAndCheckMagic(reader *ClassReader) {
    magic := reader.readUint32()
    if magic != 0xCAFEBABE {
       panic("java.lang.ClassFormatError: magic!")
    }
}

Java虛擬機(jī)規(guī)范規(guī)定,如果加載的class文件不符合要求的格式,Java虛擬機(jī)實(shí)現(xiàn)就拋出java.lang.ClassFormatError異常。

但是因?yàn)槲覀儾艅倓傞_始編寫虛擬機(jī),還無法拋出異常,所以暫時(shí)先調(diào)用 panic()方法終止程序執(zhí)行。

版本號(hào)

解析版本號(hào)

魔數(shù)之后是class文件的次版本號(hào)和主版本號(hào),都是u2類型

假設(shè)某class文件的主版本號(hào)是M,次版本號(hào)是m,那么完整的版本號(hào) 可以表示成M.m的形式。

次版本號(hào)只在J2SE 1.2之前用過,從1.2 開始基本上就沒什么用了(都是0)。

主版本號(hào)在J2SE 1.2之前是45, 從1.2開始,每次有大的Java版本發(fā)布,都會(huì)加1。

Java 版本類文件版本號(hào)
Java 1.145.3
Java 1.246.0
Java 1.347.0
Java 1.448.0
Java 549.0
Java 650.0
Java 751.0
Java 852.0

特定的Java虛擬機(jī)實(shí)現(xiàn)只能支持版本號(hào)在某個(gè)范圍內(nèi)的class文 件。

Oracle的實(shí)現(xiàn)是完全向后兼容的,比如Java SE 8支持版本號(hào)為 45.0~52.0的class文件。

如果版本號(hào)不在支持的范圍內(nèi),Java虛擬機(jī) 實(shí)現(xiàn)就拋出java.lang.UnsupportedClassVersionError異常。參考 Java 8,支持版本號(hào)為45.0~52.0的class文件。如果遇到其他版本號(hào), 調(diào)用panic()方法終止程序執(zhí)行。

如下為檢查版本號(hào)代碼:

func (self *ClassFile) readAndCheckVersion(reader *ClassReader) {
    self.minorVersion = reader.readUint16()
    self.majorVersion = reader.readUint16()
    switch self.majorVersion {
    case 45:
       return
    case 46, 47, 48, 49, 50, 51, 52:
       if self.minorVersion == 0 {
          return
       }
    }
    panic("java.lang.UnsupportedClassVersionError!")
}

解析類訪問標(biāo)識(shí)

版本號(hào)之后是常量池,但是由于常量池比較復(fù)雜,所以放到4.3 節(jié)介紹。

常量池之后是類訪問標(biāo)志,這是一個(gè)16位的bitmask,指出class文件定義的是類還是接口,訪問級(jí)別是public還是private,等等。

本章只對(duì)class文件進(jìn)行初步解析,并不做完整驗(yàn)證,所以只是讀取類訪問標(biāo)志以備后用。

ClassFileTest的類訪問標(biāo)志為:0X21:

解析類和父類索引

類訪問標(biāo)志之后是兩個(gè)u2類型的常量池索引,分別給出類名和超類名。

class文件存儲(chǔ)的類名類似完全限定名,但是把點(diǎn)換成了 斜線,Java語言規(guī)范把這種名字叫作二進(jìn)制名binary names。

因?yàn)槊總€(gè)類都有名字,所以thisClass必須是有效的常量池索引。
除 java.lang.Object之外,其他類都有超類,所以superClass只在 Object.class中是0,在其他class文件中必須是有效的常量池索引。如下,ClassFileTest的類索引是5,超類索引是6。

解析接口索引表

類和超類索引后面是接口索引表,表中存放的也是常量池索引,給出該類實(shí)現(xiàn)的所有接口的名字。ClassFileTest沒有實(shí)現(xiàn)接口, 所以接口表是空的

解析字段和方法表

接口索引表之后是字段表和方法表,分別存儲(chǔ)字段和方法信息。

字段和方法的基本結(jié)構(gòu)大致相同,差別僅在于屬性表。

下面是 Java虛擬機(jī)規(guī)范給出的字段結(jié)構(gòu)定義

field_info {
    u2 access_flags;
    u2 name_index;
    u2 descriptor_index;
    u2 attributes_count;
    attribute_info attributes[attributes_count];
}

和類一樣,字段和方法也有自己的訪問標(biāo)志。訪問標(biāo)志之后是一個(gè)常量池索引,給出字段名或方法名,然后又是一個(gè)常量池索引,給出字段或方法的描述符,最后是屬性表。

為了避免重復(fù)代 碼,用一個(gè)結(jié)構(gòu)體統(tǒng)一表示字段和方法。

package classfile
type MemberInfo struct {
    cp ConstantPool
    accessFlags uint16
    nameIndex uint16
    descriptorIndex uint16
    attributes []AttributeInfo
}
func readMembers(reader *ClassReader, cp ConstantPool) []*MemberInfo {...}
func readMember(reader *ClassReader, cp ConstantPool) *MemberInfo {...}
func (self *MemberInfo) AccessFlags() uint16 {...} // getter
func (self *MemberInfo) Name() string {...}
func (self *MemberInfo) Descriptor() string {...}

cp字段保存常量池指針,后面會(huì)用到它。readMembers()讀取字段表或方法表,代碼如下:

func readMembers(reader *ClassReader, cp ConstantPool) []*MemberInfo {
    memberCount := reader.readUint16()
    members := make([]*MemberInfo, memberCount)
    for i := range members {
       members[i] = readMember(reader, cp)
    }
    return members
}

readMember()函數(shù)讀取字段或方法數(shù)據(jù)。

func readMember(reader *ClassReader, cp ConstantPool) *MemberInfo {
    return &MemberInfo{
       cp:              cp,
       accessFlags:     reader.readUint16(),
       nameIndex:       reader.readUint16(),
       descriptorIndex: reader.readUint16(),
       attributes:      readAttributes(reader, cp),
    }
}

Name()從常量 池查找字段或方法名,Descriptor()從常量池查找字段或方法描述 符

func (self *MemberInfo) Name() string {
    return self.cp.getUtf8(self.nameIndex)
}
func (self *MemberInfo) Descriptor() string {
    return self.cp.getUtf8(self.descriptorIndex)
}

4.2.3解析常量池

常量池占據(jù)了class文件很大一部分?jǐn)?shù)據(jù),里面存放著各式各樣的常量信息,包括數(shù)字和字符串常量、類和接口名、字段和方法名,等等

創(chuàng)建constant_pool.go文件,里面定義 ConstantPool類型。

package classfile

type ConstantPool []ConstantInfo
func readConstantPool(reader *ClassReader) ConstantPool {...}
func (self ConstantPool) getConstantInfo(index uint16) ConstantInfo {...}
func (self ConstantPool) getNameAndType(index uint16) (string, string) {...}
func (self ConstantPool) getClassName(index uint16) string {...}
func (self ConstantPool) getUtf8(index uint16) string {...}

常量池實(shí)際上也是一個(gè)表,但是有三點(diǎn)需要特別注意。

表頭給出的常量池大小比實(shí)際大1。假設(shè)表頭給出的值是n,那么常量池的實(shí)際大小是n–1。

有效的常量池索引是1~n–1。0是無效索引,表示不指向任何常量。

CONSTANT_Long_infoCONSTANT_Double_info各占兩個(gè)位置。也就是說,如果常量池中存在這兩種常量,實(shí)際的常量數(shù)量比n–1還要少,而且1~n–1的某些 數(shù)也會(huì)變成無效索引。

常量池由readConstantPool()函數(shù)讀取,代碼如下:

func readConstantPool(reader *ClassReader) ConstantPool {
    cpCount := int(reader.readUint16())
    cp := make([]ConstantInfo, cpCount)

    // 索引從1開始
    for i := 1; i < cpCount; i++ {
       cp[i] = readConstantInfo(reader, cp)
       switch cp[i].(type) {
       //占兩個(gè)位置
       case *ConstantLongInfo, *ConstantDoubleInfo:
          i++
       }
    }

    return cp
}

getConstantInfo()方法按索引查找常量

func (self ConstantPool) getConstantInfo(index uint16) ConstantInfo {
    if cpInfo := self[index]; cpInfo != nil {
       return cpInfo
    }
    panic(fmt.Errorf("Invalid constant pool index: %v!", index))
}

getNameAndType()方法從常量池查找字段或方法的名字和描述符

func (self ConstantPool) getNameAndType(index uint16) (string, string) {
    ntInfo := self.getConstantInfo(index).(*ConstantNameAndTypeInfo)
    name := self.getUtf8(ntInfo.nameIndex)
    _type := self.getUtf8(ntInfo.descriptorIndex)
    return name, _type
}

getClassName()方法從常量池查找類名

func (self ConstantPool) getClassName(index uint16) string {
    classInfo := self.getConstantInfo(index).(*ConstantClassInfo)
    return self.getUtf8(classInfo.nameIndex)
}

getUtf8()方法從常量池查找UTF-8字符串

func (self ConstantPool) getUtf8(index uint16) string {
    utf8Info := self.getConstantInfo(index).(*ConstantUtf8Info)
    return utf8Info.str
}

ConstPool接口

由于常量池中存放的信息各不相同,所以每種常量的格式也不同。

常量數(shù)據(jù)的第一字節(jié)是tag,用來區(qū)分常量類型。

下面是Java 虛擬機(jī)規(guī)范給出的常量結(jié)構(gòu)

cp_info {
    u1 tag;
    u1 info[];
}

Java虛擬機(jī)規(guī)范一共定義了14種常量。創(chuàng)建constant_info.go文件,在其中定義tag常量值,代碼如下:

package classfile

// Constant pool tags
const (
    CONSTANT_Class              = 7
    CONSTANT_Fieldref           = 9
    CONSTANT_Methodref          = 10
    CONSTANT_InterfaceMethodref = 11
    CONSTANT_String             = 8
    CONSTANT_Integer            = 3
    CONSTANT_Float              = 4
    CONSTANT_Long               = 5
    CONSTANT_Double             = 6
    CONSTANT_NameAndType        = 12
    CONSTANT_Utf8               = 1
    CONSTANT_MethodHandle       = 15
    CONSTANT_MethodType         = 16
    CONSTANT_InvokeDynamic      = 18
)

定義ConstantInfo接口來表示常量信息

type ConstantInfo interface {
	readInfo(reader *ClassReader)
}
//讀取常量信息
func readConstantInfo(reader *ClassReader, cp ConstantPool) ConstantInfo {...}
func newConstantInfo(tag uint8, cp ConstantPool) ConstantInfo {...}

readInfo()方法讀取常量信息,需要由具體的常量結(jié)構(gòu)體實(shí)現(xiàn)。 readConstantInfo()函數(shù)先讀出tag值,然后調(diào)用newConstantInfo()函數(shù)創(chuàng)建具體的常量,最后調(diào)用常量的readInfo()方法讀取常量信息, 代碼如下:

func readConstantInfo(reader *ClassReader, cp ConstantPool) ConstantInfo {
    tag := reader.readUint8()
    c := newConstantInfo(tag, cp)
    c.readInfo(reader)
    return c
}

newConstantInfo()根據(jù)tag值創(chuàng)建具體的常量,代碼如下:

func newConstantInfo(tag uint8, cp ConstantPool) ConstantInfo {
    switch tag {
    case CONSTANT_Integer:
       return &ConstantIntegerInfo{}
    case CONSTANT_Float:
       return &ConstantFloatInfo{}
    case CONSTANT_Long:
       return &ConstantLongInfo{}
    case CONSTANT_Double:
       return &ConstantDoubleInfo{}
    case CONSTANT_Utf8:
       return &ConstantUtf8Info{}
    case CONSTANT_String:
       return &ConstantStringInfo{cp: cp}
    case CONSTANT_Class:
       return &ConstantClassInfo{cp: cp}
    case CONSTANT_Fieldref:
       return &ConstantFieldrefInfo{ConstantMemberrefInfo{cp: cp}}
    case CONSTANT_Methodref:
       return &ConstantMethodrefInfo{ConstantMemberrefInfo{cp: cp}}
    case CONSTANT_InterfaceMethodref:
       return &ConstantInterfaceMethodrefInfo{ConstantMemberrefInfo{cp: cp}}
    case CONSTANT_NameAndType:
       return &ConstantNameAndTypeInfo{}
    case CONSTANT_MethodType:
       return &ConstantMethodTypeInfo{}
    case CONSTANT_MethodHandle:
       return &ConstantMethodHandleInfo{}
    case CONSTANT_InvokeDynamic:
       return &ConstantInvokeDynamicInfo{}
    default:
       panic("java.lang.ClassFormatError: constant pool tag!")
    }
}

CONSTANT_Integer_info

CONSTANT_Integer_info使用4字節(jié)存儲(chǔ)整數(shù)常量,其JVM結(jié)構(gòu)定義如下:

CONSTANT_Integer_info {
    u1 tag;
    u4 bytes;
}

CONSTANT_Integer_info和后面將要介紹的其他三種數(shù)字常量無論是結(jié)構(gòu),還是實(shí)現(xiàn),都非常相似,所以把它們定義在同一個(gè)文件中。創(chuàng)建cp_numeric.go文件,在其中定義 ConstantIntegerInfo結(jié)構(gòu)體,代碼如下:

package classfile
import "math"
type ConstantIntegerInfo struct {
	val int32
}
func (self *ConstantIntegerInfo) readInfo(reader *ClassReader) {...}

readInfo()先讀取一個(gè)uint32數(shù)據(jù),然后把它轉(zhuǎn)型成int32類型, 代碼如下

func (self *ConstantIntegerInfo) readInfo(reader *ClassReader) {
    bytes := reader.readUint32()
    self.val = int32(bytes)
}

CONSTANT_Float_info

CONSTANT_Float_info使用4字節(jié)存儲(chǔ)IEEE754單精度浮點(diǎn)數(shù)常量,JVM結(jié)構(gòu)如下:

CONSTANT_Float_info {
    u1 tag;
    u4 bytes;
}

cp_numeric.go文件中定義ConstantFloatInfo結(jié)構(gòu)體,代碼如下:

type ConstantFloatInfo struct {
	val float32
}

func (self *ConstantFloatInfo) readInfo(reader *ClassReader) {
	bytes := reader.readUint32()
	self.val = math.Float32frombits(bytes)
}

CONSTANT_Long_info

CONSTANT_Long_info使用8字節(jié)存儲(chǔ)整數(shù)常量,結(jié)構(gòu)如下:

CONSTANT_Long_info {
    u1 tag;
    u4 high_bytes;
    u4 low_bytes;
}

cp_numeric.go文件中定義ConstantLongInfo結(jié)構(gòu)體,代碼如下:

type ConstantLongInfo struct {
    val int64
}

func (self *ConstantLongInfo) readInfo(reader *ClassReader) {
    bytes := reader.readUint64()
    self.val = int64(bytes)
}

CONSTANT_Double_info

最后一個(gè)數(shù)字常量是CONSTANT_Double_info,使用8字節(jié)存儲(chǔ)IEEE754雙精度浮點(diǎn)數(shù),結(jié)構(gòu)如下:

CONSTANT_Double_info {
    u1 tag;
    u4 high_bytes;
    u4 low_bytes;
}

cp_numeric.go文件中定義ConstantDoubleInfo結(jié)構(gòu)體,代碼如下:

type ConstantDoubleInfo struct {
    val float64
}

func (self *ConstantDoubleInfo) readInfo(reader *ClassReader) {
    bytes := reader.readUint64()
    self.val = math.Float64frombits(bytes)
}

CONSTANT_Utf8_info

CONSTANT_Utf8_info常量里放的是MUTF-8編碼的字符串, 結(jié)構(gòu)如下:

CONSTANT_Utf8_info {
    u1 tag;
    u2 length;
    u1 bytes[length];
}

Java類文件中使用MUTF-8(Modified UTF-8)編碼而不是標(biāo)準(zhǔn)的UTF-8,是因?yàn)镸UTF-8在某些方面更適合于在Java虛擬機(jī)內(nèi)部處理字符串。以下是一些原因:

空字符的表示: 在標(biāo)準(zhǔn)的UTF-8編碼中,空字符(U+0000)會(huì)使用單個(gè)字節(jié)0x00表示,這與C字符串中的字符串終止符相同,可能引起混淆。在MUTF-8中,空字符會(huì)使用0xC0 0x80來表示,避免了混淆。

編碼長度: MUTF-8編碼中的每個(gè)字符都使用1至3個(gè)字節(jié)來表示,這與UTF-8編碼相比更緊湊。對(duì)于大多數(shù)常見的字符集,這可以減少存儲(chǔ)和傳輸開銷。

字符的編碼范圍: MUTF-8編碼對(duì)字符的范圍進(jìn)行了限制,只包含Unicode BMP(基本多文種平面)范圍內(nèi)的字符。這些字符通常足夠用于表示Java標(biāo)識(shí)符和字符串文字。

兼容性: 早期版本的Java使用的是MUTF-8編碼,因此為了保持與早期版本的兼容性,后續(xù)版本也繼續(xù)使用MUTF-8。這有助于確保Java類文件的可互操作性。

創(chuàng)建cp_utf8.go文件,在其中定義 ConstantUtf8Info結(jié)構(gòu)體,代碼如下:

type ConstantUtf8Info struct {
    str string
}

func (self *ConstantUtf8Info) readInfo(reader *ClassReader) {
    length := uint32(reader.readUint16())
    bytes := reader.readBytes(length)
    self.str = decodeMUTF8(bytes)
}

Java序列化機(jī)制也使用了MUTF-8編碼。

java.io.DataInput和 java.io.DataOutput接口分別定義了readUTF()writeUTF()方法,可以讀寫MUTF-8編碼的字符串。

如下為簡(jiǎn)化版的java.io.DataInputStream.readUTF()

// mutf8 -> utf16 -> utf32 -> string
func decodeMUTF8(bytearr []byte) string {
    utflen := len(bytearr)
    chararr := make([]uint16, utflen)

    var c, char2, char3 uint16
    count := 0
    chararr_count := 0

    for count < utflen {
       c = uint16(bytearr[count])
       if c > 127 {
          break
       }
       count++
       chararr[chararr_count] = c
       chararr_count++
    }

    for count < utflen {
       c = uint16(bytearr[count])
       switch c >> 4 {
       case 0, 1, 2, 3, 4, 5, 6, 7:
          /* 0xxxxxxx*/
          count++
          chararr[chararr_count] = c
          chararr_count++
       case 12, 13:
          /* 110x xxxx   10xx xxxx*/
          count += 2
          if count > utflen {
             panic("malformed input: partial character at end")
          }
          char2 = uint16(bytearr[count-1])
          if char2&0xC0 != 0x80 {
             panic(fmt.Errorf("malformed input around byte %v", count))
          }
          chararr[chararr_count] = c&0x1F<<6 | char2&0x3F
          chararr_count++
       case 14:
          /* 1110 xxxx  10xx xxxx  10xx xxxx*/
          count += 3
          if count > utflen {
             panic("malformed input: partial character at end")
          }
          char2 = uint16(bytearr[count-2])
          char3 = uint16(bytearr[count-1])
          if char2&0xC0 != 0x80 || char3&0xC0 != 0x80 {
             panic(fmt.Errorf("malformed input around byte %v", (count - 1)))
          }
          chararr[chararr_count] = c&0x0F<<12 | char2&0x3F<<6 | char3&0x3F<<0
          chararr_count++
       default:
          /* 10xx xxxx,  1111 xxxx */
          panic(fmt.Errorf("malformed input around byte %v", count))
       }
    }
    // The number of chars produced may be less than utflen
    chararr = chararr[0:chararr_count]
    runes := utf16.Decode(chararr)
    return string(runes)
}
  • 初始化 chararr 數(shù)組,用于存儲(chǔ)UTF-16字符。
  • 遍歷MUTF-8字節(jié)數(shù)組中的字節(jié),根據(jù)字節(jié)的值來判斷字符的編碼方式。
  • 如果字節(jié)值小于128,表示ASCII字符,直接轉(zhuǎn)換為UTF-16并存儲(chǔ)。
  • 如果字節(jié)值在特定范圍內(nèi),表示多字節(jié)字符,需要根據(jù)UTF-8編碼規(guī)則進(jìn)行解碼。
  • 如果遇到不符合規(guī)則的字節(jié),拋出異常來處理錯(cuò)誤情況。
  • 最后,將解碼后的UTF-16字符轉(zhuǎn)換為Go字符串。

CONSTANT_String_info

CONSTANT_String_info常量表示java.lang.String字面量,結(jié)構(gòu)如下:

CONSTANT_String_info {
    u1 tag;
    u2 string_index;
}

可以看到,CONSTANT_String_info本身并不存放字符串?dāng)?shù)據(jù)

只存了常量池索引,這個(gè)索引指向一個(gè)CONSTANT_Utf8_info常量。

下創(chuàng)建cp_string.go文件,在其中定義 ConstantStringInfo結(jié)構(gòu)體

type ConstantStringInfo struct {
    cp ConstantPool
    stringIndex uint16
}

func (self *ConstantStringInfo) readInfo(reader *ClassReader) {
    self.stringIndex = reader.readUint16()
}

String()方法按索引從常量池中查找字符串:

func (self *ConstantStringInfo) String() string {
    return self.cp.getUtf8(self.stringIndex)
}

CONSTANT_Class_info

CONSTANT_Class_info常量表示類或者接口的符號(hào)引用

他是對(duì)類或者接口的符號(hào)引用。它描述的可以是當(dāng)前類型的信息,也可以描述對(duì)當(dāng)前類的引用,還可以描述對(duì)其他類的引用。JVM結(jié)構(gòu)如下:

CONSTANT_Class_info {
    u1 tag;
    u2 name_index;
}

CONSTANT_String_info類似,name_index是常量池索引,指向CONSTANT_Utf8_info常量。
創(chuàng)建 cp_class.go文件,定義ConstantClassInfo結(jié)構(gòu)體

type ConstantClassInfo struct {
    cp        ConstantPool
    nameIndex uint16
}

func (self *ConstantClassInfo) readInfo(reader *ClassReader) {
    self.nameIndex = reader.readUint16()
}
func (self *ConstantClassInfo) Name() string {
    return self.cp.getUtf8(self.nameIndex)
}

CONSTANT_NameAndType_info

CONSTANT_NameAndType_info給出字段或方法的名稱和描述符。

CONSTANT_Class_infoCONSTANT_NameAndType_info加在 一起可以唯一確定一個(gè)字段或者方法。其結(jié)構(gòu)如下:

CONSTANT_NameAndType_info {
    u1 tag;
    u2 name_index;
    u2 descriptor_index;
}

字段或方法名由name_index給出,字段或方法的描述符由descriptor_index給出。

name_indexdescriptor_index都是常量池索引,指向CONSTANT_Utf8_info常量。

Java虛擬機(jī)規(guī)范定義了一種簡(jiǎn)單的語法來描述字段和方法,可以根據(jù)下面的規(guī)則生成描述符。

一、類型描述符

  • 基本類型byte、short、char、int、long、float和double的描述符是單個(gè)字母,分別對(duì)應(yīng)B、S、C、I、J、F和D。注意,long的描述符是J 而不是L。
  • 引用類型的描述符是L+類的完全限定名+分號(hào)。
  • 數(shù)組類型的描述符是[+數(shù)組元素類型描述符

二、字段描述符

? 字段類型的描述符

三、方法描述符

? 分號(hào)分隔的參數(shù)類型描述符+返回值類型描述符,其中void返回值由單個(gè)字母V表示。

Java語言支持方法重載(override),不同的方法可 以有相同的名字,只要參數(shù)列表不同即可。

這就是為什么 CONSTANT_NameAndType_info結(jié)構(gòu)要同時(shí)包含名稱和描述符的原因。

創(chuàng)建cp_name_and_type.go文件,在其中定義ConstantName-AndTypeInfo結(jié)構(gòu)體,代碼如下:

type ConstantNameAndTypeInfo struct {
    nameIndex       uint16
    descriptorIndex uint16
}

func (self *ConstantNameAndTypeInfo) readInfo(reader *ClassReader) {
    self.nameIndex = reader.readUint16()
    self.descriptorIndex = reader.readUint16()
}

CONSTANT_Fieldref_info、 CONSTANT_Methodref_info和 CONSTANT_InterfaceMethodref_info

CONSTANT_Fieldref_info表示字段符號(hào)引用,CONSTANT_Methodref_info表示普通(非接口)方法符號(hào)引用, CONSTANT_InterfaceMethodref_info表示接口方法符號(hào)引用。這三種常量結(jié)構(gòu)一模一樣。

其中CONSTANT_Fieldref_info的結(jié)構(gòu)如下:

CONSTANT_Fieldref_info {
    u1 tag;
    u2 class_index;
    u2 name_and_type_index;
}

class_indexname_and_type_index都是常量池索引,分別指向CONSTANT_Class_infoCONSTANT_NameAndType_info常量。

創(chuàng)建cp_member_ref.go文件,定義一個(gè)統(tǒng)一的結(jié)構(gòu)體ConstantMemberrefInfo來表示這3種常量,然后定義三個(gè)結(jié)構(gòu)體“繼承”ConstantMemberrefInfo。

Go語言并沒有“繼承”這個(gè)概念,但是可以通過結(jié)構(gòu)體嵌套來模擬

type ConstantFieldrefInfo struct{ ConstantMemberrefInfo }
type ConstantMethodrefInfo struct{ ConstantMemberrefInfo }
type ConstantInterfaceMethodrefInfo struct{ ConstantMemberrefInfo }

type ConstantMemberrefInfo struct {
    cp               ConstantPool
    classIndex       uint16
    nameAndTypeIndex uint16
}

func (self *ConstantMemberrefInfo) readInfo(reader *ClassReader) {
    self.classIndex = reader.readUint16()
    self.nameAndTypeIndex = reader.readUint16()
}
func (self *ConstantMemberrefInfo) ClassName() string {
	return self.cp.getClassName(self.classIndex)
}
func (self *ConstantMemberrefInfo) NameAndDescriptor() (string, string) {
	return self.cp.getNameAndType(self.nameAndTypeIndex)
}

還有三個(gè)常量沒有介紹:CONSTANT_MethodType_info、 CONSTANT_MethodHandle_info和 CONSTANT_InvokeDynamic_info。它們是Java SE 7才添加到class文件中的,目的是支持新增的invokedynamic指令。本次暫不實(shí)現(xiàn)。

總結(jié)

可以把常量池中的常量分為兩類:字面量(literal)符號(hào)引用 (symbolic reference)。

字面量包括數(shù)字常量字符串常量符號(hào)引用包括接口名、字段方法信息等。

除了字面量,其他常量都是通過索引直接或間接指向CONSTANT_Utf8_info常量,以 CONSTANT_Fieldref_info為例,如下所示。

4.2.4解析屬性表

一些重要的信息沒有出現(xiàn),如方法的字節(jié)碼等。那么這些信息存在哪里呢?答案是屬性表。

AttributeInfo接口

和常量池類似,各種屬性表達(dá)的信息也各不相同,因此無法用統(tǒng)一的結(jié)構(gòu)來定義。不同之處在于,常量是由Java虛擬機(jī)規(guī)范嚴(yán)格 定義的,共有14種。

但屬性是可以擴(kuò)展的,不同的虛擬機(jī)實(shí)現(xiàn)可以定義自己的屬性類型。

由于這個(gè)原因,Java虛擬機(jī)規(guī)范沒有使用tag,而是使用屬性名來區(qū)別不同的屬性。

屬性數(shù)據(jù)放在屬性名之后的u1表中,這樣Java虛擬機(jī)實(shí)現(xiàn)就可以跳過自己無法識(shí)別的屬性。 屬性的結(jié)構(gòu)定義如下:

attribute_info {
    u2 attribute_name_index;
    u4 attribute_length;
    u1 info[attribute_length];
}

屬性表中存放的屬性名實(shí)際上并不是編碼后的字符串, 而是常量池索引,指向常量池中的CONSTANT_Utf8_info常量。

創(chuàng)建attribute_info.go文件,在其中定義 AttributeInfo接口

package classfile
type AttributeInfo interface {
	readInfo(reader *ClassReader)
}
func readAttributes(reader *ClassReader, cp ConstantPool) []AttributeInfo {...}
func readAttribute(reader *ClassReader, cp ConstantPool) AttributeInfo {...}
func newAttributeInfo(attrName string, attrLen uint32,cp ConstantPool) AttributeInfo {...}

ConstantInfo接口一樣,AttributeInfo接口也只定義了一個(gè)readInfo()方法,需要由具體的屬性實(shí)現(xiàn)。readAttributes()函數(shù)讀取屬性表。

func readAttributes(reader *ClassReader, cp ConstantPool) []AttributeInfo {
    attributesCount := reader.readUint16()
    attributes := make([]AttributeInfo, attributesCount)
    for i := range attributes {
       attributes[i] = readAttribute(reader, cp)
    }
    return attributes
}

讀取單個(gè)屬性函數(shù):

func readAttribute(reader *ClassReader, cp ConstantPool) AttributeInfo {
    attrNameIndex := reader.readUint16()
    attrName := cp.getUtf8(attrNameIndex)
    attrLen := reader.readUint32()
    attrInfo := newAttributeInfo(attrName, attrLen, cp)
    attrInfo.readInfo(reader)
    return attrInfo
}

readAttribute()先讀取屬性名索引,根據(jù)它從常量池中找到屬性名,然后讀取屬性長度,接著調(diào)用newAttributeInfo()函數(shù)創(chuàng)建具體的屬性實(shí)例。

Java虛擬機(jī)規(guī)范預(yù)定義了23種屬性,先解析其中的8種。newAttributeInfo()函數(shù)的代碼如下

func newAttributeInfo(attrName string, attrLen uint32, cp ConstantPool) AttributeInfo {
    switch attrName {
    case "Code":
       return &CodeAttribute{cp: cp}
    case "ConstantValue":
       return &ConstantValueAttribute{}
    case "Deprecated":
       return &DeprecatedAttribute{}
    case "Exceptions":
       return &ExceptionsAttribute{}
    case "LineNumberTable":
       return &LineNumberTableAttribute{}
    case "LocalVariableTable":
       return &LocalVariableTableAttribute{}
    case "SourceFile":
       return &SourceFileAttribute{cp: cp}
    case "Synthetic":
       return &SyntheticAttribute{}
    default:
       return &UnparsedAttribute{attrName, attrLen, nil}
    }
}

創(chuàng)建attr_unparsed.go文件中,定義UnparsedAttribute結(jié)構(gòu)體

package classfile

/*
attribute_info {
    u2 attribute_name_index;
    u4 attribute_length;
    u1 info[attribute_length];
}
*/
type UnparsedAttribute struct {
    name   string
    length uint32
    info   []byte
}

func (self *UnparsedAttribute) readInfo(reader *ClassReader) {
    self.info = reader.readBytes(self.length)
}

func (self *UnparsedAttribute) Info() []byte {
    return self.info
}

按照用途,23種預(yù)定義屬性可以分為三組。

  • 第一組屬性是實(shí)現(xiàn) Java虛擬機(jī)所必需的,共有5種;
  • 第二組屬性是Java類庫所必需的,共有12種;
  • 第三組屬性主要提供給工具使用,共有6種。

第三組屬性是可選的,也就是說可以不出現(xiàn)在class文件中。如果class文件中存在第三組屬性,Java虛擬機(jī)實(shí)現(xiàn)或者Java類庫也是可以利用它們 的,比如使用LineNumberTable屬性在異常堆棧中顯示行號(hào)。

如下給出了這23 種屬性出現(xiàn)的Java版本、分組以及它們?cè)赾lass文件中的位置。

Deprecated和Synthetic屬性

DeprecatedSynthetic是最簡(jiǎn)單的兩種屬性,僅起標(biāo)記作用,不包含任何數(shù)據(jù)。

這兩種屬性都是JDK1.1引入的,可以出現(xiàn)在 ClassFile、field_info和method_info結(jié)構(gòu)中,它們的結(jié)構(gòu)定義如下:

Deprecated_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
}
Synthetic_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
}

由于不包含任何數(shù)據(jù),所以attribute_length的值必須是0。

Deprecated屬性用于指出類、接口、字段或方法已經(jīng)不建議使用,編譯器等工具可以根據(jù)Deprecated屬性輸出警告信息。

J2SE 5.0之前 可以使用Javadoc提供的@deprecated標(biāo)簽指示編譯器給類、接口、字段或方法添加Deprecated屬性,語法格式如下:

/** @deprecated */
public void oldMethod() {...}

J2SE 5.0開始,也可以使用@Deprecated注解,語法格式如下:

@Deprecated
public void oldMethod() {}

在Java中,編譯器可能會(huì)生成一些額外的方法、字段或類,用于支持內(nèi)部的匿名內(nèi)部類、枚舉、泛型等特性。這些生成的元素可能會(huì)被標(biāo)記為 Synthetic。

創(chuàng)建attr_markers.go文件,在其中定義 DeprecatedAttributeSyntheticAttribute結(jié)構(gòu)體,代碼如下:

package classfile
type DeprecatedAttribute struct { MarkerAttribute }
type SyntheticAttribute struct { MarkerAttribute }
type MarkerAttribute struct{}
func (self *MarkerAttribute) readInfo(reader *ClassReader) {
// read nothing
}

SourceFile屬性

SourceFile 屬性是Java類文件中的一個(gè)屬性,它用于指定源文件的名稱,即生成該類文件的源代碼文件的名稱。這個(gè)屬性并不直接影響類的運(yùn)行時(shí)行為。其結(jié)構(gòu)定義如下:

SourceFile_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
    u2 sourcefile_index;
}

attribute_length的值必須是2。sourcefile_index是常量池索引, 指向CONSTANT_Utf8_info常量

創(chuàng)建 attr_source_file.go文件,在其中定義SourceFileAttribute結(jié)構(gòu)體,代碼如下:

package classfile
type SourceFileAttribute struct {
    cp ConstantPool
    sourceFileIndex uint16
}
func (self *SourceFileAttribute) readInfo(reader *ClassReader) {
	self.sourceFileIndex = reader.readUint16()
}
func (self *SourceFileAttribute) FileName() string {
	return self.cp.getUtf8(self.sourceFileIndex)
}

例如,如果有一個(gè)名為 MyClass.java 的源代碼文件,它包含以下類:

public class MyClass {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}

當(dāng)編譯 MyClass.java 文件時(shí),會(huì)生成一個(gè)名為 MyClass.class 的類文件,并在其中添加一個(gè) SourceFile 屬性,將其值設(shè)置為 MyClass.java。

ConstantValue屬性

ConstantValue 屬性是Java類文件中的一個(gè)屬性,通常與字段(field)相關(guān)聯(lián)。這個(gè)屬性的作用是為字段提供一個(gè)常量初始值。這意味著,如果您在類中聲明一個(gè)字段,并為其分配了 ConstantValue 屬性,那么該字段的初始值將在類加載時(shí)被設(shè)置為 ConstantValue 中指定的常量。

ConstantValue_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
    u2 constantvalue_index;
}

例如,假設(shè)有以下Java代碼:

public class MyClass {
    public final int myField = 42;
}

在對(duì)應(yīng)的類文件中,將包含一個(gè) ConstantValue 屬性,指定了常量值 42,并與 myField 字段相關(guān)聯(lián)。當(dāng)類加載時(shí),myField 將被初始化為 42

constantvalue_index是常量池索引,具體指向哪種常量因字段類型而異,如下為對(duì)照表

創(chuàng)建attr_constant_value.go文件,在其中定義ConstantValueAttribute結(jié)構(gòu)體,代碼如下:

package classfile
type ConstantValueAttribute struct {
	constantValueIndex uint16
}
func (self *ConstantValueAttribute) readInfo(reader *ClassReader) {
	self.constantValueIndex = reader.readUint16()
}
func (self *ConstantValueAttribute) ConstantValueIndex() uint16 {
	return self.constantValueIndex
}

Code屬性

Code 屬性是Java類文件中的一個(gè)屬性,通常與方法(Method)相關(guān)聯(lián)。

它包含了方法的字節(jié)碼指令,即實(shí)際的可執(zhí)行代碼。Code 屬性是Java類文件中最重要的屬性之一,因?yàn)樗朔椒ǖ膶?shí)際執(zhí)行邏輯。

以下是關(guān)于 Code 屬性的一些重要信息:

屬性結(jié)構(gòu)Code 屬性通常包含以下信息:

  • 最大堆棧深度(max_stack):方法執(zhí)行時(shí)所需的最大堆棧深度。
  • 局部變量表的大?。?code>max_locals):方法內(nèi)部局部變量表的大小。
  • 字節(jié)碼指令(code):實(shí)際的字節(jié)碼指令序列,即方法的執(zhí)行代碼。
  • 異常處理器列表(exception_table):用于捕獲和處理異常的信息。
  • 方法屬性(attributes):其他與方法相關(guān)的屬性,例如局部變量表、行號(hào)映射表等。

字節(jié)碼指令Code 屬性中的 code 部分包含了方法的實(shí)際字節(jié)碼指令,這些指令由Java虛擬機(jī)執(zhí)行。每個(gè)指令執(zhí)行一些特定的操作,例如加載、存儲(chǔ)、算術(shù)操作、分支、方法調(diào)用等。

異常處理Code 屬性中的 exception_table 部分包含了異常處理器的信息,指定了哪些字節(jié)碼范圍可以拋出哪些異常,并且指定了如何處理這些異常。

局部變量表Code 屬性中的局部變量表(max_locals)用于存儲(chǔ)方法執(zhí)行期間的局部變量,例如方法參數(shù)和臨時(shí)變量。

屬性Code 屬性中還可以包含其他屬性,如局部變量表、行號(hào)映射表等,這些屬性提供了更多的調(diào)試和運(yùn)行時(shí)信息。

Code 屬性是Java虛擬機(jī)實(shí)際執(zhí)行方法的關(guān)鍵部分,它描述了方法的行為和操作,包括如何處理輸入和生成輸出。編譯器將源代碼編譯為字節(jié)碼,然后將字節(jié)碼填充到 Code 屬性中,這使得Java程序可以在虛擬機(jī)上執(zhí)行。

創(chuàng)建attr_code.go文件,定義CodeAttribute結(jié)構(gòu)體、ExceptionTableEntry結(jié)構(gòu)體,代碼如下:

type CodeAttribute struct {
	cp             ConstantPool
	maxStack       uint16
	maxLocals      uint16
	code           []byte
	exceptionTable []*ExceptionTableEntry
	attributes     []AttributeInfo
}

func (self *CodeAttribute) readInfo(reader *ClassReader) {
	self.maxStack = reader.readUint16()
	self.maxLocals = reader.readUint16()
	codeLength := reader.readUint32()
	self.code = reader.readBytes(codeLength)
	self.exceptionTable = readExceptionTable(reader)
	self.attributes = readAttributes(reader, self.cp)
}
type ExceptionTableEntry struct {
    startPc   uint16
    endPc     uint16
    handlerPc uint16
    catchType uint16
}

func readExceptionTable(reader *ClassReader) []*ExceptionTableEntry {
    exceptionTableLength := reader.readUint16()
    exceptionTable := make([]*ExceptionTableEntry, exceptionTableLength)
    for i := range exceptionTable {
       exceptionTable[i] = &ExceptionTableEntry{
          startPc:   reader.readUint16(),
          endPc:     reader.readUint16(),
          handlerPc: reader.readUint16(),
          catchType: reader.readUint16(),
       }
    }
    return exceptionTable
}

Exceptions屬性

Exceptions屬性通常與方法(Method)相關(guān)聯(lián),用于指定方法可能拋出的受檢查異常(checked exceptions)的列表。

Exceptions_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
    u2 number_of_exceptions;
    u2 exception_index_table[number_of_exceptions];
}

創(chuàng)建attr_exceptions.go文件,在其中定義ExceptionsAttribute結(jié)構(gòu)體

type ExceptionsAttribute struct {
    exceptionIndexTable []uint16
}

func (self *ExceptionsAttribute) readInfo(reader *ClassReader) {
    self.exceptionIndexTable = reader.readUint16s()
}

func (self *ExceptionsAttribute) ExceptionIndexTable() []uint16 {
    return self.exceptionIndexTable
}

LineNumberTable和LocalVariableTable屬性

LineNumberTable 和 LocalVariableTable 屬性是Java類文件中的兩個(gè)用于調(diào)試和運(yùn)行時(shí)跟蹤的屬性,它們包含了與源代碼中行號(hào)和局部變量相關(guān)的信息。

LineNumberTable 屬性:用于建立源代碼行號(hào)和字節(jié)碼指令之間的映射。它允許開發(fā)工具在調(diào)試時(shí)將異常棧軌跡映射到源代碼的特定行,以便開發(fā)者可以更容易地定位和修復(fù)代碼中的問題。結(jié)構(gòu)如下:

LineNumberTable {
    u2 attribute_name_index;
    u4 attribute_length;
    u2 line_number_table_length;
    {
        u2 start_pc;
        u2 line_number;
    } line_number_table[line_number_table_length];
}

LocalVariableTable 屬性:用于跟蹤局部變量的信息,包括局部變量的名稱、數(shù)據(jù)類型、作用域范圍和字節(jié)碼偏移。

創(chuàng)建attr_line_number_table.go文件,定義LineNumberTableAttribute結(jié)構(gòu)體,代碼如下:

type LineNumberTableAttribute struct {
    lineNumberTable []*LineNumberTableEntry
}

type LineNumberTableEntry struct {
    startPc    uint16
    lineNumber uint16
}

func (self *LineNumberTableAttribute) readInfo(reader *ClassReader) {
    lineNumberTableLength := reader.readUint16()
    self.lineNumberTable = make([]*LineNumberTableEntry, lineNumberTableLength)
    for i := range self.lineNumberTable {
       self.lineNumberTable[i] = &LineNumberTableEntry{
          startPc:    reader.readUint16(),
          lineNumber: reader.readUint16(),
       }
    }
}

func (self *LineNumberTableAttribute) GetLineNumber(pc int) int {
    for i := len(self.lineNumberTable) - 1; i >= 0; i-- {
       entry := self.lineNumberTable[i]
       if pc >= int(entry.startPc) {
          return int(entry.lineNumber)
       }
    }
    return -1
}

創(chuàng)建attr_local_variable_table.go文件,定義LocalVariableTableAttribute,代碼如下:

type LocalVariableTableAttribute struct {
    localVariableTable []*LocalVariableTableEntry
}

type LocalVariableTableEntry struct {
    startPc         uint16
    length          uint16
    nameIndex       uint16
    descriptorIndex uint16
    index           uint16
}

func (self *LocalVariableTableAttribute) readInfo(reader *ClassReader) {
    localVariableTableLength := reader.readUint16()
    self.localVariableTable = make([]*LocalVariableTableEntry, localVariableTableLength)
    for i := range self.localVariableTable {
       self.localVariableTable[i] = &LocalVariableTableEntry{
          startPc:         reader.readUint16(),
          length:          reader.readUint16(),
          nameIndex:       reader.readUint16(),
          descriptorIndex: reader.readUint16(),
          index:           reader.readUint16(),
       }
    }
}

4.3測(cè)試

打開ch03\main.go文件,修改import語句和startJVM()函數(shù),代碼如下:

package main

import "fmt"
import "strings"
import "jvmgo/ch03/classfile"
import "jvmgo/ch03/classpath"

func main() {
    cmd := parseCmd()

    if cmd.versionFlag {
       fmt.Println("version 0.0.1")
    } else if cmd.helpFlag || cmd.class == "" {
       printUsage()
    } else {
       startJVM(cmd)
    }
}

func startJVM(cmd *Cmd) {
    cp := classpath.Parse(cmd.XjreOption, cmd.cpOption)
    className := strings.Replace(cmd.class, ".", "/", -1)
    cf := loadClass(className, cp)
    fmt.Println(cmd.class)
    printClassInfo(cf)
}

func loadClass(className string, cp *classpath.Classpath) *classfile.ClassFile {
    classData, _, err := cp.ReadClass(className)
    if err != nil {
       panic(err)
    }

    cf, err := classfile.Parse(classData)
    if err != nil {
       panic(err)
    }

    return cf
}

func printClassInfo(cf *classfile.ClassFile) {
    fmt.Printf("version: %v.%v\n", cf.MajorVersion(), cf.MinorVersion())
    fmt.Printf("constants count: %v\n", len(cf.ConstantPool()))
    fmt.Printf("access flags: 0x%x\n", cf.AccessFlags())
    fmt.Printf("this class: %v\n", cf.ClassName())
    fmt.Printf("super class: %v\n", cf.SuperClassName())
    fmt.Printf("interfaces: %v\n", cf.InterfaceNames())
    fmt.Printf("fields count: %v\n", len(cf.Fields()))
    for _, f := range cf.Fields() {
       fmt.Printf("  %s\n", f.Name())
    }
    fmt.Printf("methods count: %v\n", len(cf.Methods()))
    for _, m := range cf.Methods() {
       fmt.Printf("  %s\n", m.Name())
    }
}

首先go install jvmgo\ch03 生產(chǎn)ch03.exe

然后執(zhí)行,并輸入命令行語句,得到結(jié)果如下:

  • version: 52.0:這表示 java.lang.String 類的類文件版本為 52.0。類文件版本號(hào)與Java版本號(hào)有關(guān),52.0 對(duì)應(yīng)于Java 8。
  • constants count: 548:這表示常量池中包含 548 個(gè)常量。常量池包含了類的常量、方法、字段等信息。
  • access flags: 0x31:這表示類的訪問標(biāo)志,0x31 是十六進(jìn)制表示,對(duì)應(yīng)于二進(jìn)制 00110001。這些標(biāo)志描述類的訪問權(quán)限和特性。
  • this class: java/lang/String:這表示類的名稱,即 java.lang.String。
  • super class: java/lang/Object:這表示 java.lang.String 類繼承自 java.lang.Object 類。
  • interfaces: [java/io/Serializable java/lang/Comparable java/lang/CharSequence]:這表示 java.lang.String 類實(shí)現(xiàn)了三個(gè)接口,分別是 Serializable、Comparable 和 CharSequence
  • fields count: 5:這表示 java.lang.String 類包含 5 個(gè)字段。
  • methods count: 94:這表示 java.lang.String 類包含 94 個(gè)方法。其中一些是構(gòu)造方法(<init>),其他是實(shí)例方法。

以上就是Golang實(shí)現(xiàn)Java虛擬機(jī)之解析class文件詳解的詳細(xì)內(nèi)容,更多關(guān)于Go實(shí)現(xiàn)Java虛擬機(jī)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Golang基于內(nèi)存的鍵值存儲(chǔ)緩存庫go-cache

    Golang基于內(nèi)存的鍵值存儲(chǔ)緩存庫go-cache

    go-cache是一個(gè)內(nèi)存中的key:value store/cache庫,適用于單機(jī)應(yīng)用程序,本文主要介紹了Golang基于內(nèi)存的鍵值存儲(chǔ)緩存庫go-cache,具有一定的參考價(jià)值,感興趣的可以了解一下
    2025-03-03
  • go的切片擴(kuò)容機(jī)制詳解

    go的切片擴(kuò)容機(jī)制詳解

    本文主要介紹了go的切片擴(kuò)容機(jī)制詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • 手把手帶你走進(jìn)Go語言之運(yùn)算符解析

    手把手帶你走進(jìn)Go語言之運(yùn)算符解析

    這篇文章主要介紹了手Go語言之運(yùn)算符解析,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-09-09
  • Go語言集成開發(fā)環(huán)境之VS Code安裝使用

    Go語言集成開發(fā)環(huán)境之VS Code安裝使用

    VS Code是微軟開源的一款編輯器,插件系統(tǒng)十分的豐富,下面介紹如何用VS Code搭建go語言開發(fā)環(huán)境,需要的朋友可以參考下
    2021-10-10
  • Go語言實(shí)現(xiàn)定時(shí)器的方法

    Go語言實(shí)現(xiàn)定時(shí)器的方法

    這篇文章主要介紹了Go語言實(shí)現(xiàn)定時(shí)器的方法,涉及Go語言時(shí)間操作技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-02-02
  • CGO編程基礎(chǔ)快速入門

    CGO編程基礎(chǔ)快速入門

    這篇文章主要為大家介紹了CGO編程基礎(chǔ)快速入門示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • Golang分布式注冊(cè)中心實(shí)現(xiàn)流程講解

    Golang分布式注冊(cè)中心實(shí)現(xiàn)流程講解

    這篇文章主要介紹了Golang分布式注冊(cè)中心實(shí)現(xiàn)流程,注冊(cè)中心可以用于服務(wù)發(fā)現(xiàn),服務(wù)注冊(cè),配置管理等方面,在分布式系統(tǒng)中,服務(wù)的發(fā)現(xiàn)和注冊(cè)是非常重要的組成部分,需要的朋友可以參考下
    2023-05-05
  • go語言實(shí)現(xiàn)兩個(gè)協(xié)程交替打印

    go語言實(shí)現(xiàn)兩個(gè)協(xié)程交替打印

    這篇文章主要介紹了go語言實(shí)現(xiàn)兩個(gè)協(xié)程交替打印,文章主要分享了兩種方法使用兩個(gè)channel和使用一個(gè)channel,內(nèi)容介紹詳細(xì)具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-03-03
  • Go一站式配置管理工具Viper的使用教程

    Go一站式配置管理工具Viper的使用教程

    Viper是一個(gè)方便Go語言應(yīng)用程序處理配置信息的庫,它可以處理多種格式的配置,這篇文章主要為大家介紹了它的具體使用教程,需要的可以參考下
    2023-08-08
  • Go調(diào)用opencv實(shí)現(xiàn)圖片矯正的代碼示例

    Go調(diào)用opencv實(shí)現(xiàn)圖片矯正的代碼示例

    這篇文章主要為大家詳細(xì)介紹了Go調(diào)用opencv實(shí)現(xiàn)圖片矯正的代碼示例,文中的示例代碼簡(jiǎn)潔易懂,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-09-09

最新評(píng)論

午夜久久久久久久精品熟女| 夜女神免费福利视频| av日韩在线免费播放| 日本五十路熟新垣里子| 最新的中文字幕 亚洲| av破解版在线观看| 干逼又爽又黄又免费的视频| 在线不卡日韩视频播放| 中文字幕第三十八页久久| 天天射夜夜操狠狠干| 国产三级精品三级在线不卡| 欧美一区二区三区啪啪同性| 日本精品美女在线观看| 国产精品久久久久网| 成年人的在线免费视频| 白白操白白色在线免费视频| 国产亚洲成人免费在线观看| 日韩欧美国产一区不卡| 红桃av成人在线观看| 天天日天天透天天操| 天天日天天添天天爽| 欧洲日韩亚洲一区二区三区| 精品一区二区三区在线观看| 硬鸡巴动态操女人逼视频| 成年女人免费播放视频| 超碰在线观看免费在线观看| 适合午夜一个人看的视频| 99精品国产自在现线观看| gav成人免费播放| 最近的中文字幕在线mv视频| 做爰视频毛片下载蜜桃视频1| 亚洲 自拍 色综合图| 在线网站你懂得老司机| 青青青国产片免费观看视频| 狠狠鲁狠狠操天天晚上干干| 免费手机黄页网址大全| 日本熟妇色熟妇在线观看| 人人人妻人人澡人人| 蜜臀av久久久久蜜臀av麻豆| 中出中文字幕在线观看| 福利一二三在线视频观看| 国产精品久久久久久久女人18| 性感美女福利视频网站| 欧美日韩一级黄片免费观看| 日韩二区视频一线天婷婷五| 亚洲人妻av毛片在线| 国产91久久精品一区二区字幕 | 亚洲最大黄了色网站| 午夜精品久久久久久99热| 精品久久久久久久久久久久人妻| 亚洲熟女女同志女同| 久久麻豆亚洲精品av| 青青社区2国产视频| 欧美va不卡视频在线观看| 91久久精品色伊人6882| 天天操天天干天天艹| 日本丰满熟妇大屁股久久| 欧美乱妇无乱码一区二区| 欧美成一区二区三区四区| 国产成人精品久久二区91| 91九色porny国产在线| 性生活第二下硬不起来| 亚洲自拍偷拍综合色| 夜夜骑夜夜操夜夜奸| 亚洲另类伦春色综合小| 亚洲精品在线资源站| 国产九色91在线观看精品| 适合午夜一个人看的视频| 中国熟女@视频91| 在线视频免费观看网| 精内国产乱码久久久久久| 11久久久久久久久久久| 18禁无翼鸟成人在线| 美女视频福利免费看| 日本韩国免费福利精品| 亚洲精品欧美日韩在线播放| 亚洲精品无码久久久久不卡| 色婷婷久久久久swag精品| 中文字幕一区二区亚洲一区| 国产精品一区二区久久久av| 国产精品熟女久久久久浪潮| 操人妻嗷嗷叫视频一区二区| 国产美女一区在线观看| 在线观看免费视频色97| 美味人妻2在线播放| 超黄超污网站在线观看| free性日本少妇| 性欧美日本大妈母与子| 最新国产亚洲精品中文在线| 国产成人精品一区在线观看| 国产在线观看黄色视频| 国产一区自拍黄视频免费观看| 丰满少妇人妻xxxxx| 黑人解禁人妻叶爱071| 青青草原网站在线观看| jiujiure精品视频在线| av中文字幕在线观看第三页| 自拍偷拍 国产资源| 大学生A级毛片免费视频| 日韩av熟妇在线观看| 亚洲成人三级在线播放| 日韩熟女系列一区二区三区| 晚上一个人看操B片| 国产av福利网址大全| 天天干天天操天天玩天天射| 日本韩国在线观看一区二区| 天天日天天舔天天射进去| 亚洲一区自拍高清免费视频| 女同互舔一区二区三区| 日本性感美女三级视频| 美女av色播在线播放| 免费看高清av的网站| 亚洲欧美成人综合在线观看| 孕妇奶水仑乱A级毛片免费看| 初美沙希中文字幕在线 | 18禁美女黄网站色大片下载| 蜜桃视频入口久久久| 亚洲精品久久视频婷婷| 青春草视频在线免费播放| 最新欧美一二三视频| 玩弄人妻熟妇性色av少妇| 国产高清97在线观看视频| 久久精品久久精品亚洲人| 亚洲精品国偷自产在线观看蜜桃| 女生自摸在线观看一区二区三区| av在线免费观看亚洲天堂| 少妇深喉口爆吞精韩国| 国产美女午夜福利久久| 91人妻精品久久久久久久网站| 国产视频精品资源网站| 直接观看免费黄网站| 日韩精品二区一区久久| 性感美女福利视频网站| 黑人变态深video特大巨大| 日本www中文字幕| 538精品在线观看视频| 韩国女主播精品视频网站| 在线国产日韩欧美视频| 91综合久久亚洲综合| 亚洲2021av天堂| 美女张开腿让男生操在线看| 亚洲成人国产av在线| 欧美专区第八页一区在线播放 | 成年人的在线免费视频| 欧美日韩在线精品一区二区三| 黄色大片男人操女人逼| 亚洲va天堂va国产va久| 第一福利视频在线观看| 人人在线视频一区二区| 4个黑人操素人视频网站精品91| 日韩美av高清在线| 国产极品美女久久久久久| 午夜精品福利一区二区三区p | 综合激情网激情五月五月婷婷| 97精品视频在线观看| 啪啪啪操人视频在线播放| 一区二区三区综合视频| 天天干天天爱天天色| 日本免费一级黄色录像| 日韩欧美制服诱惑一区在线| 又粗又长 明星操逼小视频 | 国产精品久久久久久久女人18| 国产亚洲精品视频合集| 中文字幕 亚洲av| 91成人在线观看免费视频| 91精品一区二区三区站长推荐| 国产精品久久久久国产三级试频| 国产精品大陆在线2019不卡| 操操网操操伊剧情片中文字幕网| 国产麻豆剧传媒精品国产av蜜桃| 黄色三级网站免费下载| 国产亚洲成人免费在线观看| 一区二区三区久久久91| av视网站在线观看| 日本av熟女在线视频| 久久久久久久一区二区三| 国产实拍勾搭女技师av在线| 日韩欧美中文国产在线| 亚洲av黄色在线网站| 国产精品人妻66p| 少妇人妻久久久久视频黄片| 久久人人做人人妻人人玩精品vr| 大鸡吧插逼逼视频免费看| av无限看熟女人妻另类av| 亚洲精品乱码久久久久久密桃明| 91亚洲国产成人精品性色| 人妻av无码专区久久绿巨人| 国产性生活中老年人视频网站| 久草视频 久草视频2| 欧美精品久久久久久影院| 天天日天天舔天天射进去| 黄色的网站在线免费看| 红杏久久av人妻一区| 三级黄色亚洲成人av| 久久热这里这里只有精品| 亚洲免费视频欧洲免费视频| 偷拍自拍视频图片免费| 日本午夜爽爽爽爽爽视频在线观看| 91中文字幕免费在线观看| 91人妻精品一区二区在线看| 国产夫妻视频在线观看免费| 五月精品丁香久久久久福利社| 午夜精品亚洲精品五月色| 国产高清女主播在线| 人人爱人人妻人人澡39| 天天做天天爽夜夜做少妇| 五月色婷婷综合开心网4438| 亚洲熟妇x久久av久久| 成人区人妻精品一区二视频| 免费观看理论片完整版| 精品av国产一区二区三区四区| 国产一区二区在线欧美| 伊人日日日草夜夜草| 日韩精品激情在线观看| 中文字幕免费福利视频6| 国产极品美女久久久久久| 精品日产卡一卡二卡国色天香 | 亚洲国产欧美一区二区丝袜黑人| 99热99re在线播放| 国产又大又黄免费观看| 狠狠鲁狠狠操天天晚上干干| 中文字幕无码一区二区免费| 亚洲人妻30pwc| 久久久久久九九99精品| 欧美 亚洲 另类综合| 免费福利av在线一区二区三区| 日韩欧美制服诱惑一区在线| 青青草国内在线视频精选| 一级黄色av在线观看| 天天干天天日天天干天天操| 黄页网视频在线免费观看| 色花堂在线av中文字幕九九| 九色porny九色9l自拍视频| 欧美久久一区二区伊人| 亚洲免费va在线播放| 丰满熟女午夜福利视频| 亚洲欧美精品综合图片小说| 天天干天天操天天扣| 亚洲av成人免费网站| 狠狠躁夜夜躁人人爽天天久天啪| 亚洲熟妇久久无码精品| 日视频免费在线观看| 欧美在线精品一区二区三区视频| 偷青青国产精品青青在线观看| 国产成人小视频在线观看无遮挡| 宅男噜噜噜666免费观看| 精品一区二区三区三区色爱| 国产真实灌醉下药美女av福利| 日本韩国亚洲综合日韩欧美国产| 亚洲高清一区二区三区视频在线| 天天躁日日躁狠狠躁躁欧美av| 国产精品人妻熟女毛片av久| 久久精品国产999| 97人妻无码AV碰碰视频| 在线视频国产欧美日韩| 人妻无码中文字幕专区| 91色网站免费在线观看| 97超碰免费在线视频| 一区二区三区日韩久久| 韩国亚洲欧美超一级在线播放视频 | 大黑人性xxxxbbbb| 久久尻中国美女视频| 人妻凌辱欧美丰满熟妇| 久久艹在线观看视频| 天堂av在线最新版在线| 国产高清女主播在线| 最新中文字幕乱码在线| 人妻丝袜av在线播放网址| 三级等保密码要求条款| 亚洲美女自偷自拍11页| 日韩北条麻妃一区在线| 久久精品美女免费视频| 老司机午夜精品视频资源| 亚洲熟妇x久久av久久| 五十路熟女av天堂| 2o22av在线视频| 亚洲狠狠婷婷综合久久app| 国产日韩一区二区在线看| 成人av免费不卡在线观看| 久久精品在线观看一区二区| 激情图片日韩欧美人妻| 97超碰最新免费在线观看| 被大鸡吧操的好舒服视频免费| 国产精品国产精品一区二区| 2020av天堂网在线观看| 视频二区在线视频观看| 亚洲av可乐操首页| 免费十精品十国产网站| 天天日天天干天天要| 最新国产精品拍在线观看| 亚洲日产av一区二区在线| 亚洲综合图片20p| 97少妇精品在线观看| 青青青青青青青青青国产精品视频| 国产精品自拍在线视频| 顶级尤物粉嫩小尤物网站| 亚洲午夜电影之麻豆| 在线视频自拍第三页| 91桃色成人网络在线观看| 懂色av蜜桃a v| 97人妻无码AV碰碰视频| 欧美成人精品欧美一级黄色| 欧洲日韩亚洲一区二区三区 | 91精品国产黑色丝袜| 九色porny九色9l自拍视频| 亚洲 欧美 精品 激情 偷拍| 免费十精品十国产网站| 国产午夜亚洲精品不卡在线观看| 激情图片日韩欧美人妻| 五月精品丁香久久久久福利社| 69精品视频一区二区在线观看| 在线视频国产欧美日韩| 日韩成人免费电影二区| 亚洲精品三级av在线免费观看| 在线免费观看国产精品黄色| 国产熟妇乱妇熟色T区| 久久久极品久久蜜桃| 中文字幕1卡1区2区3区| 国产成人无码精品久久久电影| 亚洲精品午夜久久久久| 亚洲 欧美 精品 激情 偷拍| 中文字幕亚洲久久久| 啪啪啪18禁一区二区三区 | 99热久久这里只有精品| 国产日韩欧美视频在线导航| 偷拍美女一区二区三区| 午夜久久久久久久精品熟女| 黄色男人的天堂视频| yy6080国产在线视频| 在线观看av亚洲情色| 中文字幕无码一区二区免费| 国产女人被做到高潮免费视频 | 姐姐的朋友2在线观看中文字幕| av在线观看网址av| 亚洲在线观看中文字幕av| 黑人大几巴狂插日本少妇| 国产chinesehd精品麻豆| 日本www中文字幕| 1000部国产精品成人观看视频| 亚洲成人三级在线播放| 国产白嫩美女一区二区| 日日夜夜狠狠干视频| 夜夜骑夜夜操夜夜奸| 天天操夜夜骑日日摸| 亚洲美女高潮喷浆视频| 国产黄色a级三级三级三级| 日韩欧美在线观看不卡一区二区| 少妇系列一区二区三区视频| 很黄很污很色的午夜网站在线观看| 青青擦在线视频国产在线| 熟女视频一区,二区,三区| 亚洲少妇人妻无码精品| 密臀av一区在线观看| 亚洲av第国产精品| 欧美另类重口味极品在线观看| 欧美日韩熟女一区二区三区| 大鸡巴操娇小玲珑的女孩逼| 黄色成人在线中文字幕| 3344免费偷拍视频| 欧美成人综合视频一区二区| 国产熟妇一区二区三区av | 在线观看视频网站麻豆| 国产在线观看免费人成短视频| 自拍偷拍亚洲欧美在线视频| 精品人人人妻人人玩日产欧| 鸡巴操逼一级黄色气| 午夜精品福利一区二区三区p | 久久麻豆亚洲精品av| av在线播放国产不卡| gogo国模私拍视频| 一区二区三区的久久的蜜桃的视频| 日本熟女50视频免费| 最近的中文字幕在线mv视频| 中文字幕成人日韩欧美| 北条麻妃肉色丝袜视频| 天天日天天干天天爱| 欧美一区二区中文字幕电影| 免费费一级特黄真人片| 丝袜长腿第一页在线| 自拍偷拍亚洲精品第2页| 亚洲美女自偷自拍11页| 最新国产精品拍在线观看| 粉嫩小穴流水视频在线观看| 老鸭窝在线观看一区| 人妻自拍视频中国大陆| 亚洲精品在线资源站| 午夜久久久久久久99| av无限看熟女人妻另类av| 欧美aa一级一区三区四区 | 91天堂天天日天天操| 亚洲人妻av毛片在线| 99国内精品永久免费视频| 欧美视频中文一区二区三区| 午夜在线观看岛国av,com| 狠狠嗨日韩综合久久| 日本一本午夜在线播放| 免费十精品十国产网站| 亚洲自拍偷拍综合色| 青青草视频手机免费在线观看| 欧美精品激情在线最新观看视频| 久久这里有免费精品| 黄色片一级美女黄色片| 99国产精品窥熟女精品| 蜜臀av久久久久蜜臀av麻豆| 国产精品中文av在线播放| 亚洲精品无码久久久久不卡| 日韩熟女系列一区二区三区| 欧美激情电影免费在线| 亚洲国产成人在线一区| 中国黄色av一级片| 韩国一级特黄大片做受| 一区二区三区美女毛片| 亚洲精品麻豆免费在线观看| 午夜福利人人妻人人澡人人爽| 国产美女午夜福利久久| 三级黄色亚洲成人av| 在线观看视频一区麻豆| 国产高清精品极品美女| 亚洲卡1卡2卡三卡四老狼| 国产免费高清视频视频| 日韩精品啪啪视频一道免费| 成年午夜免费无码区| 欧美aa一级一区三区四区| 中文字幕免费福利视频6| 动漫美女的小穴视频| 日日摸夜夜添夜夜添毛片性色av| av中文字幕在线导航| 免费无毒热热热热热热久| yy96视频在线观看| 中文字幕日韩精品日本| 国产精品精品精品999| 一二三中文乱码亚洲乱码one| 成人亚洲国产综合精品| 亚洲国产成人无码麻豆艾秋| 不卡一区一区三区在线| okirakuhuhu在线观看| 9l人妻人人爽人人爽| 亚洲av午夜免费观看| av中文字幕在线导航| 精品91高清在线观看| 男人操女人的逼免费视频| 亚洲精品无码久久久久不卡| 成人精品视频99第一页| 阴茎插到阴道里面的视频| 国产亚洲四十路五十路| 4个黑人操素人视频网站精品91| 老熟妇凹凸淫老妇女av在线观看| 国产高清在线观看1区2区| 午夜激情精品福利视频| 亚洲 清纯 国产com| 一区二区麻豆传媒黄片| 亚洲Av无码国产综合色区| 狠狠躁夜夜躁人人爽天天天天97| 99久久99一区二区三区| 五十路息与子猛烈交尾视频| 漂亮 人妻被中出中文| 中文字幕国产专区欧美激情| 狠狠的往里顶撞h百合| 男女第一次视频在线观看| 国产黄色大片在线免费播放| 偷拍美女一区二区三区| 亚洲免费成人a v| 久草视频在线看免费| 欧美麻豆av在线播放| 2022天天干天天操| 国产V亚洲V天堂无码欠欠| 岳太深了紧紧的中文字幕| 91免费观看在线网站| 免费费一级特黄真人片| 欧美专区第八页一区在线播放| 夜色17s精品人妻熟女| 国产福利小视频免费观看| 丝袜肉丝一区二区三区四区在线 | 亚洲一区二区三区五区| 午夜极品美女福利视频| 日韩加勒比东京热二区| 老鸭窝日韩精品视频观看| 偷青青国产精品青青在线观看| 人妻无码色噜噜狠狠狠狠色| 在线制服丝袜中文字幕| 青青青国产免费视频| 亚洲老熟妇日本老妇| 成人动漫大肉棒插进去视频| 国产精彩福利精品视频| 亚洲无线观看国产高清在线| 国产一级精品综合av| 色花堂在线av中文字幕九九 | 2022国产综合在线干| 国产精品免费不卡av| 国产高清精品一区二区三区| 欧美一区二区三区四区性视频| 黄色大片免费观看网站| 亚洲午夜高清在线观看| 搡老妇人老女人老熟女| 91传媒一区二区三区| 99精品免费久久久久久久久a| 欧美黄色录像免费看的| 青青青青青青青在线播放视频| 欧洲日韩亚洲一区二区三区| 日韩欧美国产一区不卡| 成熟丰满熟妇高潮xx×xx| 男女第一次视频在线观看| 一本一本久久a久久精品综合不卡 亚洲另类综合一区小说 | 国产精品成人xxxx| 中文字幕熟女人妻久久久| 久久精品亚洲成在人线a| 欧美性受xx黑人性猛交| 99精品免费久久久久久久久a| 人妻少妇精品久久久久久| av手机在线免费观看日韩av| 狠狠躁夜夜躁人人爽天天久天啪| 在线视频精品你懂的| 久久久人妻一区二区| 中文字幕在线免费第一页| 欧美精产国品一二三区| 啪啪啪操人视频在线播放| 日日日日日日日日夜夜夜夜夜夜| 自拍偷拍亚洲精品第2页| 丝袜亚洲另类欧美变态| 亚洲超碰97人人做人人爱| 日本人妻欲求不满中文字幕| 日韩成人综艺在线播放| 婷婷久久久综合中文字幕| 日本美女成人在线视频| 日本性感美女视频网站| 亚洲欧美激情人妻偷拍| 91色九色porny| 国产精彩福利精品视频| 中文字幕 人妻精品| 九色精品视频在线播放| 夏目彩春在线中文字幕| 中文字幕无码一区二区免费| 亚洲少妇高潮免费观看| 综合国产成人在线观看| 亚洲1卡2卡三卡4卡在线观看| 在线观看视频一区麻豆| 亚洲成人av一区在线| 亚洲视频在线视频看视频在线| 亚洲护士一区二区三区| 日韩欧美一级黄片亚洲| 中文字幕一区二区人妻电影冢本| 亚洲熟色妇av日韩熟色妇在线| 午夜大尺度无码福利视频| 一区二区三区在线视频福利| 99婷婷在线观看视频| 亚洲的电影一区二区三区| 亚洲在线免费h观看网站| 狠狠操操操操操操操操操| huangse网站在线观看| 国产亚洲精品欧洲在线观看| 二区中出在线观看老师 | 人妻少妇一区二区三区蜜桃| 男女之间激情网午夜在线| 亚洲精品国产综合久久久久久久久| 91老熟女连续高潮对白| 在线观看视频 你懂的| 国产亚洲成人免费在线观看| 国产精品成人xxxx| 午夜久久久久久久精品熟女| 亚洲区欧美区另类最新章节| 91传媒一区二区三区| 香港三日本三韩国三欧美三级| 后入美女人妻高清在线| 97国产在线av精品| 日韩加勒比东京热二区| 色天天天天射天天舔| 日韩剧情片电影在线收看| 综合激情网激情五月五月婷婷| 激情人妻校园春色亚洲欧美 | 亚洲av午夜免费观看| 免费观看污视频网站| 一色桃子久久精品亚洲 | 亚洲日本一区二区久久久精品| 中文字幕日本人妻中出| 后入美女人妻高清在线| 欧美专区第八页一区在线播放| 久久久久久9999久久久久| 欧美女同性恋免费a| 亚洲精品国品乱码久久久久| 亚洲 自拍 色综合图| 国产精品视频一区在线播放| 婷婷午夜国产精品久久久| 免费男阳茎伸入女阳道视频| 中文字幕无码日韩专区免费| 天天日夜夜干天天操| 国产成人精品久久二区91| 欧美特色aaa大片| 男人的天堂av日韩亚洲| 在线观看的a站 最新| 免费岛国喷水视频在线观看 | 久久久久久97三级| 亚洲精品三级av在线免费观看| 在线视频精品你懂的| 一区二区三区在线视频福利| 99av国产精品欲麻豆| 亚洲高清国产拍青青草原| 人人妻人人澡欧美91精品| 免费看美女脱光衣服的视频| 91天堂天天日天天操| 午夜久久久久久久99| 性欧美日本大妈母与子| av视网站在线观看| 丝袜美腿欧美另类 中文字幕| 亚洲另类在线免费观看| aiss午夜免费视频| 亚洲人成精品久久久久久久| 又色又爽又黄又刺激av网站| jul—619中文字幕在线| 班长撕开乳罩揉我胸好爽| 欧美日韩激情啪啪啪| 欧美成人小视频在线免费看| 护士特殊服务久久久久久久| 亚洲欧洲一区二区在线观看| 国语对白xxxx乱大交| 国产精品久久综合久久| 免费在线播放a级片| 精品久久久久久久久久久久人妻| 1区2区3区4区视频在线观看| av俺也去在线播放| 成年美女黄网站18禁久久| 99久久99久国产黄毛片| 中国黄色av一级片| 午夜精品一区二区三区4| 大胆亚洲av日韩av| 青娱乐极品视频青青草| 绝色少妇高潮3在线观看| 中文字幕奴隷色的舞台50| 久久久久久性虐视频| 欧美成人猛片aaaaaaa| 欧美黑人与人妻精品| 年轻的人妻被夫上司侵犯| 亚洲中文字字幕乱码| 日韩av有码一区二区三区4| 免费岛国喷水视频在线观看| 啊慢点鸡巴太大了啊舒服视频| 国产密臀av一区二区三| 成熟熟女国产精品一区| 青青青视频手机在线观看| 色在线观看视频免费的| 香蕉aⅴ一区二区三区| 午夜青青草原网在线观看| 伊人综合免费在线视频| 2018最新中文字幕在线观看| av网址国产在线观看| 少妇与子乱在线观看| 欧美精品资源在线观看| 又大又湿又爽又紧A视频| 中文亚洲欧美日韩无线码| 在线观看视频污一区| 亚洲av日韩高清hd| gav成人免费播放| 免费观看成年人视频在线观看| 午夜精品亚洲精品五月色| 成人亚洲国产综合精品| 天天色天天操天天舔| 人妻久久久精品69系列| 久久热久久视频在线观看| 视频 一区二区在线观看| 亚洲1区2区3区精华液| 自拍偷拍一区二区三区图片| 蜜桃视频入口久久久| 天天做天天干天天舔| 国产综合视频在线看片| 小穴多水久久精品免费看| 1769国产精品视频免费观看| 91精品国产91久久自产久强| 在线成人日韩av电影| 偷偷玩弄新婚人妻h视频| 欧美亚洲偷拍自拍色图| 91试看福利一分钟| 91福利在线视频免费观看| 在线免费91激情四射 | 亚洲av无乱一区二区三区性色 | 黑人解禁人妻叶爱071| 亚洲熟女久久久36d| 手机看片福利盒子日韩在线播放| 精品乱子伦一区二区三区免费播| 欧美精品激情在线最新观看视频| 亚洲国产在人线放午夜| 亚洲少妇人妻无码精品| 日韩一个色综合导航| 亚洲一区二区激情在线| 美女吃鸡巴操逼高潮视频| 新97超碰在线观看| 久久精品久久精品亚洲人| 欧美美女人体视频一区| 四川乱子伦视频国产vip| 久久久久久9999久久久久| 免费看国产又粗又猛又爽又黄视频 | 亚洲男人让女人爽的视频| 青娱乐在线免费视频盛宴| 亚洲成人午夜电影在线观看| 欧美国产亚洲中英文字幕| 国产精品中文av在线播放 | 久草视频福利在线首页| 欧美成人猛片aaaaaaa| 80电影天堂网官网| 成人精品视频99第一页| 日本福利午夜电影在线观看| 少妇一区二区三区久久久| 黑人解禁人妻叶爱071| 早川濑里奈av黑人番号| 亚洲熟女女同志女同| 18禁美女黄网站色大片下载| 青草久久视频在线观看| 密臀av一区在线观看| 91天堂精品一区二区| 亚洲综合图片20p| 天天操天天干天天插| 午夜久久久久久久精品熟女| 久草电影免费在线观看| 又色又爽又黄的美女裸体| 专门看国产熟妇的网站| 免费男阳茎伸入女阳道视频 | 亚洲国产欧美一区二区三区久久 | 国产黑丝高跟鞋视频在线播放| 鸡巴操逼一级黄色气| aiss午夜免费视频| 亚洲美女自偷自拍11页| 欧美精品一二三视频| 精品国产在线手机在线| 黄色的网站在线免费看| 午夜在线观看岛国av,com| 亚洲天天干 夜夜操| 午夜极品美女福利视频| 亚洲成人线上免费视频观看| 国产成人无码精品久久久电影| 蜜桃视频入口久久久| 超碰97免费人妻麻豆| 亚洲免费福利一区二区三区| 绝顶痉挛大潮喷高潮无码 | 国产性色生活片毛片春晓精品| 午夜激情精品福利视频| 日比视频老公慢点好舒服啊| 色哟哟国产精品入口| 啊用力插好舒服视频| 成年人该看的视频黄免费| 精品人人人妻人人玩日产欧| 高清成人av一区三区| 国产成人自拍视频播放| 大香蕉伊人国产在线| 亚洲成人情色电影在线观看| 偷偷玩弄新婚人妻h视频| 亚洲区美熟妇久久久久| 亚洲国产免费av一区二区三区| 日本性感美女视频网站| 亚洲成人午夜电影在线观看| 亚洲福利午夜久久久精品电影网 | 少妇ww搡性bbb91| av手机在线观播放网站| 亚洲av男人的天堂你懂的| 日本美女性生活一级片| av网址在线播放大全| 777奇米久久精品一区| 精品老妇女久久9g国产| 天天干天天操天天玩天天射| 91国偷自产一区二区三区精品| av网站色偷偷婷婷网男人的天堂| 成人伊人精品色xxxx视频| 动漫黑丝美女的鸡巴| www天堂在线久久| 亚洲精品成人网久久久久久小说| 日韩国产乱码中文字幕| 天天干天天操天天爽天天摸| 日韩美在线观看视频黄| 大香蕉伊人国产在线| 成人动漫大肉棒插进去视频| 在线观看视频污一区| 欧美一区二区中文字幕电影| 人妻丝袜榨强中文字幕| 91www一区二区三区| 国产欧美精品一区二区高清| 日韩国产乱码中文字幕| 中文字幕高清免费在线人妻 | 欧美一级色视频美日韩| 99re久久这里都是精品视频| 国产成人精品久久二区91| 天堂av中文在线最新版| 操日韩美女视频在线免费看| 一区二区免费高清黄色视频| 日韩视频一区二区免费观看| 换爱交换乱高清大片| 我想看操逼黄色大片| 在线观看黄色成年人网站| 久草视频中文字幕在线观看| 国产精品伦理片一区二区| 久久尻中国美女视频| 欧美亚洲中文字幕一区二区三区 | 日日夜夜大香蕉伊人| 亚洲丝袜老师诱惑在线观看| 成人av中文字幕一区| 亚洲激情偷拍一区二区| 国产综合精品久久久久蜜臀| av天堂中文字幕最新| 18禁无翼鸟成人在线| 日韩欧美亚洲熟女人妻| 黄片三级三级三级在线观看| 毛片一级完整版免费| 免费男阳茎伸入女阳道视频 | 毛片一级完整版免费| 亚洲最大免费在线观看| 爆乳骚货内射骚货内射在线| 日本精品视频不卡一二三| 青青青青爽手机在线| 最新97国产在线视频| 一区二区三区久久久91| 精品欧美一区二区vr在线观看| 激情五月婷婷免费视频| 国产亚洲视频在线二区| 无码中文字幕波多野不卡| 成人网18免费视频版国产| 久久99久久99精品影院| 中文字幕无码一区二区免费| 亚洲精品在线资源站| 骚逼被大屌狂草视频免费看| 精品国产乱码一区二区三区乱| 91中文字幕免费在线观看| 91国偷自产一区二区三区精品| 日本少妇在线视频大香蕉在线观看| 黄色视频在线观看高清无码| 精品一区二区三区三区88| 操日韩美女视频在线免费看 | 东京干手机福利视频| 午夜美女福利小视频| 中文字幕乱码人妻电影| 欧洲欧美日韩国产在线| 久草极品美女视频在线观看| 91自产国产精品视频| 晚上一个人看操B片| 亚洲男人的天堂a在线| 美女福利视频网址导航| 色爱av一区二区三区| 日本啪啪啪啪啪啪啪| 9色精品视频在线观看| 中文字幕AV在线免费看 | 蜜臀成人av在线播放| 91九色porny蝌蚪国产成人| 9久在线视频只有精品| 女同久久精品秋霞网| 日视频免费在线观看| 日本中文字幕一二区视频| 日本韩国免费一区二区三区视频| 日本a级视频老女人| 日日操夜夜撸天天干| 中文字幕熟女人妻久久久| 国产日韩欧美视频在线导航| 桃色视频在线观看一区二区| 欧美一区二区三区乱码在线播放| 青青草精品在线视频观看| 亚洲欧美激情国产综合久久久 | 日本午夜爽爽爽爽爽视频在线观看| 国产视频网站一区二区三区| 亚洲伊人色一综合网| 午夜成午夜成年片在线观看| 欧美男同性恋69视频| 黄页网视频在线免费观看| 中文字幕熟女人妻久久久| 91免费观看国产免费| 亚洲 欧美 自拍 偷拍 在线| 91破解版永久免费| 91麻豆精品传媒国产黄色片| 天天操天天射天天操天天天| 一区二区三区激情在线| 一区二区三区 自拍偷拍| 成人激情文学网人妻| 丝袜国产专区在线观看| 成人性爱在线看四区| av中文字幕电影在线看| av中文字幕国产在线观看| 国产精品成久久久久三级蜜臀av| 亚洲第一黄色在线观看| 啊啊啊视频试看人妻| 午夜精品福利一区二区三区p | 久久久久久国产精品| 亚洲成人国产综合一区| 免费男阳茎伸入女阳道视频| 国产精选一区在线播放| 亚洲蜜臀av一区二区三区九色 | 日本熟女50视频免费| 适合午夜一个人看的视频| 天堂av在线最新版在线| 国产露脸对白在线观看| 亚洲av自拍天堂网| 美女吃鸡巴操逼高潮视频| 一区二区三区在线视频福利| 国产亚洲精品视频合集| 青青青青青青青在线播放视频| 成人免费做爰高潮视频| 亚洲美女自偷自拍11页| 日韩精品中文字幕福利| 亚洲一区二区三区久久午夜| 国产精品精品精品999| 欧美成人小视频在线免费看| 亚洲午夜伦理视频在线| 91人妻精品一区二区久久| 91亚洲国产成人精品性色| 一区二区三区视频,福利一区二区 丰满的子国产在线观看 | 国产亚洲视频在线二区| av俺也去在线播放| 五十路熟女人妻一区二| 在线免费视频 自拍| 巨乳人妻日下部加奈被邻居中出| 在线观看av观看av| 一区二区在线观看少妇| 一区二区三区久久中文字幕| av老司机亚洲一区二区| 绝顶痉挛大潮喷高潮无码| 久久农村老妇乱69系列| 中文字日产幕乱六区蜜桃| 人人妻人人爽人人添夜| 综合一区二区三区蜜臀| 一级黄片大鸡巴插入美女 | 天天艹天天干天天操| 亚洲精品无码色午夜福利理论片| 东京干手机福利视频| 任你操视频免费在线观看| 综合激情网激情五月五月婷婷| 少妇高潮一区二区三区| 国产在线免费观看成人| 狍和女人的王色毛片| 2020久久躁狠狠躁夜夜躁| 日本免费视频午夜福利视频| 白嫩白嫩美女极品国产在线观看| 91精品资源免费观看| 91桃色成人网络在线观看| 青青青青草手机在线视频免费看| 国际av大片在线免费观看| 久久精品美女免费视频| 在线观看一区二区三级| av老司机亚洲一区二区| 啪啪啪18禁一区二区三区| 中文字幕在线一区精品| 蜜臀成人av在线播放| 日韩av中文在线免费观看| 动漫精品视频在线观看| 男生舔女生逼逼视频| jul—619中文字幕在线| 亚洲精品久久综合久| 日韩中文字幕在线播放第二页| 天天日天天操天天摸天天舔 | 青青热久免费精品视频在线观看| 青娱乐蜜桃臀av色| 一区二区三区国产精选在线播放| 视频一区二区三区高清在线| 久久亚洲天堂中文对白| 国产精品免费不卡av| 91啪国自产中文字幕在线| 动漫黑丝美女的鸡巴| 国产在线一区二区三区麻酥酥| 亚洲 中文 自拍 无码| 青青青aaaa免费| 精品久久久久久高潮| 亚洲天天干 夜夜操| 一区二区三区四区中文| chinese国产盗摄一区二区| 亚洲免费av在线视频| 视频久久久久久久人妻| av欧美网站在线观看| 亚洲人一区二区中文字幕| 韩国三级aaaaa高清视频 | av成人在线观看一区| 影音先锋女人av噜噜色| 超碰在线观看免费在线观看| 黄色视频在线观看高清无码| 国产真实灌醉下药美女av福利| 爱爱免费在线观看视频| 亚国产成人精品久久久| aiss午夜免费视频| 黄片大全在线观看观看| 久草视频在线看免费| 日韩成人性色生活片| 亚洲午夜伦理视频在线 | av老司机精品在线观看| 亚洲av色图18p| 亚洲国产成人在线一区| 男女之间激情网午夜在线| 成人性爱在线看四区| 人妻另类专区欧美制服| 性感美女福利视频网站| 人妻3p真实偷拍一二区| 一区二区三区欧美日韩高清播放| 久久久久久99国产精品| 成年人该看的视频黄免费| 蜜桃臀av蜜桃臀av| 国产一区成人在线观看视频| 少妇被强干到高潮视频在线观看 | 午夜精品久久久久麻豆影视| 欧美一区二区三区四区性视频| 经典av尤物一区二区| 亚洲狠狠婷婷综合久久app| 伊人精品福利综合导航| 欧美日本国产自视大全| AV无码一区二区三区不卡| 91av中文视频在线| 亚洲av自拍天堂网| 久久午夜夜伦痒痒想咳嗽P| 亚洲精品国产综合久久久久久久久 | 日本裸体熟妇区二区欧美| 2018最新中文字幕在线观看| 2022天天干天天操| 日韩不卡中文在线视频网站| 中文字幕日本人妻中出| 在线观看免费岛国av| 人妻素人精油按摩中出| 大香蕉伊人国产在线| 亚洲 自拍 色综合图| 亚洲欧美自拍另类图片| 视频在线免费观看你懂得| 九色porny九色9l自拍视频| 桃色视频在线观看一区二区| 宅男噜噜噜666免费观看| 亚洲视频在线视频看视频在线| 亚洲精品 欧美日韩| 男女啪啪啪啪啪的网站| 国产麻豆剧传媒精品国产av蜜桃| 顶级尤物粉嫩小尤物网站| 超碰97人人澡人人| 久久午夜夜伦痒痒想咳嗽P| 免费69视频在线看| 91香蕉成人app下载| 亚洲av日韩高清hd| 日韩中文字幕精品淫| 78色精品一区二区三区| av在线免费观看亚洲天堂| 天天色天天操天天舔| 女同性ⅹxx女同hd| 国产一线二线三线的区别在哪| 青青操免费日综合视频观看| 亚洲激情偷拍一区二区| 久久精品美女免费视频| 日韩欧美制服诱惑一区在线| 狠狠的往里顶撞h百合| 国产成人精品久久二区91 | av新中文天堂在线网址| 精品一区二区三区三区色爱| 午夜av一区二区三区| 国产a级毛久久久久精品| 黄色三级网站免费下载| 亚洲 中文 自拍 另类 欧美| 18禁无翼鸟成人在线| 中国黄色av一级片| 香蕉aⅴ一区二区三区| 午夜在线观看岛国av,com| 欧美老鸡巴日小嫩逼| 欧美久久久久久三级网| 亚洲激情偷拍一区二区| 又色又爽又黄的美女裸体| 亚洲第一黄色在线观看| 黄色中文字幕在线播放| 精品一区二区三区午夜| 一区二区在线观看少妇| 中文字幕日韩精品就在这里| 北条麻妃高跟丝袜啪啪| 亚洲色偷偷综合亚洲AV伊人| 亚洲特黄aaaa片| 熟女91pooyn熟女| 日韩欧美高清免费在线| 美女被肏内射视频网站| 久久久久久97三级| 骚逼被大屌狂草视频免费看| 超碰在线中文字幕一区二区| 动漫美女的小穴视频| 亚洲成人精品女人久久久| 青青青青青青青青青青草青青| 欧美亚洲偷拍自拍色图| 天美传媒mv视频在线观看| 非洲黑人一级特黄片| 欧美精品 日韩国产| 精品老妇女久久9g国产| 噜噜色噜噜噜久色超碰| 日本啪啪啪啪啪啪啪| 91在线免费观看成人| 国产亚洲视频在线二区| 免费十精品十国产网站| 水蜜桃一区二区三区在线观看视频 | 人妻少妇av在线观看| 精内国产乱码久久久久久| 欧美在线一二三视频| 99热久久这里只有精品| 中文字幕高清免费在线人妻| 一二三区在线观看视频| 中国无遮挡白丝袜二区精品| 好吊操视频这里只有精品| 人妻少妇av在线观看| 搡老熟女一区二区在线观看| 亚洲高清免费在线观看视频| 亚洲美女自偷自拍11页| 粉嫩欧美美人妻小视频| 亚洲区美熟妇久久久久| 青青青爽视频在线播放| 新97超碰在线观看| 国产一区二区欧美三区| 国产在线自在拍91国语自产精品 | 337p日本大胆欧美人| 日本人妻欲求不满中文字幕| 欧美亚洲牲夜夜综合久久| 国产日韩精品一二三区久久久| 绝色少妇高潮3在线观看| 欧美精品激情在线最新观看视频| 国产真实乱子伦a视频| 91精品国产麻豆国产| 免费成人av中文字幕| 新97超碰在线观看| 中文字幕在线永久免费播放| 国产高清在线在线视频| 亚洲精品国品乱码久久久久| 精品久久久久久久久久中文蒉| 亚洲福利天堂久久久久久| 欧美精品一区二区三区xxxx| 中文字幕视频一区二区在线观看| 一区二区熟女人妻视频| 精品黑人一区二区三区久久国产| 国产精品视频欧美一区二区| 高潮喷水在线视频观看| 国产视频一区二区午夜| 黄片色呦呦视频免费看| 在线免费观看国产精品黄色| 黄色大片免费观看网站| 成人免费做爰高潮视频| 天天干天天操天天扣| 在线网站你懂得老司机| 2019av在线视频| 国产麻豆91在线视频| 91精品国产麻豆国产| 97国产福利小视频合集| 动漫黑丝美女的鸡巴| 熟女91pooyn熟女| 最近的中文字幕在线mv视频| 欧美特色aaa大片| 亚洲公开视频在线观看| 亚洲人妻国产精品综合| 熟女视频一区,二区,三区| 亚洲欧美日韩视频免费观看| 少妇露脸深喉口爆吞精| 人妻熟女在线一区二区| 不卡日韩av在线观看| 日日夜夜狠狠干视频| 亚洲精品亚洲人成在线导航 | 日本美女成人在线视频| 福利国产视频在线观看| 亚洲欧美福利在线观看| 欧美精品免费aaaaaa| 欧美性受xx黑人性猛交| 91人妻精品一区二区久久| 日韩美在线观看视频黄| 日韩人妻丝袜中文字幕| av视屏免费在线播放| aiss午夜免费视频| 成人亚洲国产综合精品| 国产精品久久久久久久精品视频| 久久h视频在线观看| 中文字幕—97超碰网| 天天做天天干天天操天天射| 天天日天天舔天天射进去| 欧美成一区二区三区四区| 视频在线亚洲一区二区| 91九色国产porny蝌蚪| 天天干天天操天天玩天天射 | 女人精品内射国产99| 99久久中文字幕一本人| 精品亚洲在线免费观看| 国产精品一区二区三区蜜臀av| 亚洲一区二区久久久人妻| 亚洲综合在线观看免费| 亚洲男人让女人爽的视频| 欧美女同性恋免费a| 亚洲精品三级av在线免费观看| 2022中文字幕在线| av手机在线观播放网站| 亚洲一级 片内射视正片| 亚洲第一黄色在线观看| 人人妻人人爽人人澡人人精品| 天堂资源网av中文字幕| 另类av十亚洲av| av手机在线观播放网站| 亚洲欧美一区二区三区电影| 美女吃鸡巴操逼高潮视频| 女警官打开双腿沦为性奴| 高潮喷水在线视频观看| 伊人情人综合成人久久网小说| 丰满熟女午夜福利视频| 97精品人妻一区二区三区精品| 日韩三级黄色片网站| 极品丝袜一区二区三区| 二区中出在线观看老师| 夜色撩人久久7777| 亚洲男人在线天堂网| 1769国产精品视频免费观看| 日本一道二三区视频久久| 免费看国产av网站| 日本一区精品视频在线观看| 人妻3p真实偷拍一二区| 少妇ww搡性bbb91| 中文字幕人妻三级在线观看| 亚洲福利精品福利精品福利| 亚洲国产40页第21页| 99的爱精品免费视频| 人妻熟女中文字幕aⅴ在线| 亚洲av日韩高清hd| 天天摸天天日天天操| 最新国产亚洲精品中文在线| 中文字幕日韩人妻在线三区| 97精品综合久久在线| 欧美熟妇一区二区三区仙踪林| 天天摸天天日天天操| 自拍偷拍日韩欧美亚洲| 日本熟妇一区二区x x| 精品欧美一区二区vr在线观看 | 91精品视频在线观看免费| 在线观看免费视频色97| 国产janese在线播放| 2019av在线视频| 国产中文精品在线观看| 亚洲中文精品人人免费| 国产无遮挡裸体免费直播视频| 午夜国产免费福利av| 中文字幕免费在线免费| 亚洲粉嫩av一区二区三区| 国产日韩精品免费在线| 中文字幕中文字幕 亚洲国产| 日韩美女搞黄视频免费| 日本三极片视频网站观看| 在线免费视频 自拍| 国产视频在线视频播放| 在线免费观看国产精品黄色| 欧美成人精品在线观看| 亚洲精品无码久久久久不卡| 亚洲精品一线二线在线观看| 伊人成人在线综合网| av中文字幕网址在线| 精品国产在线手机在线| 宅男噜噜噜666国产| 中文字日产幕乱六区蜜桃| 亚洲高清国产自产av| 日本性感美女写真视频| 伊人开心婷婷国产av| weyvv5国产成人精品的视频| 国产中文字幕四区在线观看| 午夜激情精品福利视频| 9久在线视频只有精品| 欧美成人小视频在线免费看| 男人操女人逼逼视频网站| 亚洲熟色妇av日韩熟色妇在线| 国产chinesehd精品麻豆| 99久久成人日韩欧美精品| 婷婷综合蜜桃av在线| v888av在线观看视频| 国产精品久久久久久美女校花| 老熟妇xxxhd老熟女| 偷拍自拍亚洲美腿丝袜| 欲满人妻中文字幕在线| 一区二区三区av高清免费| 五十路丰满人妻熟妇| 自拍偷拍日韩欧美亚洲| 亚洲中文字幕国产日韩| 国产在线自在拍91国语自产精品| 亚洲免费在线视频网站| aⅴ五十路av熟女中出| 欧美区一区二区三视频| 午夜成午夜成年片在线观看 | 色秀欧美视频第一页| 99re国产在线精品| 日本av高清免费网站| 国产又色又刺激在线视频| 最新的中文字幕 亚洲| 国产不卡av在线免费| 操日韩美女视频在线免费看| 18禁免费av网站| 亚洲人成精品久久久久久久| 精品suv一区二区69| 亚洲欧美综合另类13p| 国产精彩对白一区二区三区 | 免费69视频在线看| 视频一区二区在线免费播放| 丝袜长腿第一页在线| 色爱av一区二区三区| 99精品免费观看视频| 中英文字幕av一区| 日本美女成人在线视频| 欧美日韩熟女一区二区三区| 同居了嫂子在线播高清中文| 亚洲区美熟妇久久久久| 欧美3p在线观看一区二区三区| 亚洲专区激情在线观看视频| 日本啪啪啪啪啪啪啪| 天天日天天日天天射天天干| 国产剧情演绎系列丝袜高跟| 99精品国自产在线人| 日韩激情文学在线视频| 91精品高清一区二区三区| 在线 中文字幕 一区| 午夜精品福利91av| 蜜桃久久久久久久人妻| 欧美偷拍自拍色图片| 青青青国产片免费观看视频| 可以在线观看的av中文字幕| 日比视频老公慢点好舒服啊| 成人久久精品一区二区三区| 人妻爱爱 中文字幕| 伊人日日日草夜夜草| 成熟丰满熟妇高潮xx×xx| 中文字幕最新久久久| 国产真实灌醉下药美女av福利| 亚洲国产美女一区二区三区软件| 日韩av有码一区二区三区4| 综合国产成人在线观看| 大屁股肉感人妻中文字幕在线| av成人在线观看一区| 亚洲一区制服丝袜美腿| 免费福利av在线一区二区三区| 欧美精品一二三视频| 国产精品一二三不卡带免费视频 | 人妻丝袜av在线播放网址| 久久久人妻一区二区| 久久精品国产亚洲精品166m| 亚洲精品国产久久久久久| 亚洲久久午夜av一区二区| 视频一区 视频二区 视频| 日韩近亲视频在线观看| 免费国产性生活视频| okirakuhuhu在线观看| 日韩精品激情在线观看| 国产高清在线观看1区2区| av完全免费在线观看av| 久久这里只有精品热视频| 午夜久久香蕉电影网| 99精品免费久久久久久久久a| 老司机免费福利视频网| 欧美精品资源在线观看| 91小伙伴中女熟女高潮| 日韩精品中文字幕播放| 18禁无翼鸟成人在线| aⅴ五十路av熟女中出| 亚洲免费va在线播放| 91高清成人在线视频| 任你操任你干精品在线视频| 亚洲高清国产一区二区三区| 揄拍成人国产精品免费看视频 | av天堂中文免费在线| 天天日天天玩天天摸| 精品人妻一二三区久久| 青青青青青免费视频| 日本av高清免费网站| 美女av色播在线播放| 日韩精品一区二区三区在线播放| 天堂av在线播放免费| 这里只有精品双飞在线播放| 影音先锋女人av噜噜色| 欧美亚洲免费视频观看| 大陆胖女人与丈夫操b国语高清| 成人久久精品一区二区三区| 天堂av在线官网中文| 在线免费观看靠比视频的网站| 啪啪啪18禁一区二区三区 | 国产1区,2区,3区| 亚洲少妇高潮免费观看| 成人av天堂丝袜在线观看| 亚洲av午夜免费观看| 国产在线一区二区三区麻酥酥| 在线观看911精品国产| 夜色17s精品人妻熟女| 亚洲午夜精品小视频| 大学生A级毛片免费视频| 91综合久久亚洲综合| tube69日本少妇| 不卡精品视频在线观看| 又粗又硬又猛又爽又黄的| 亚洲国产美女一区二区三区软件| 日本裸体熟妇区二区欧美| 最新国产精品拍在线观看| 2021国产一区二区| 一区二区三区美女毛片| 最新国产亚洲精品中文在线| 伊人日日日草夜夜草| 亚洲天堂成人在线观看视频网站| 六月婷婷激情一区二区三区| 亚洲熟色妇av日韩熟色妇在线| 欧美一区二区中文字幕电影 | 人人人妻人人澡人人| 91大神福利视频网| 男人的天堂在线黄色| 18禁无翼鸟成人在线 | 97人妻人人澡爽人人精品| 亚洲中文精品字幕在线观看| 亚洲国产精品免费在线观看| 青娱乐最新视频在线| 午夜青青草原网在线观看| 色爱av一区二区三区| av在线资源中文字幕| 久久久久久久久久性潮| 91欧美在线免费观看| 亚洲卡1卡2卡三卡四老狼| 老司机你懂得福利视频| 亚洲偷自拍高清视频| 天天插天天色天天日| 日韩亚洲高清在线观看| 国产精品免费不卡av| 美女小视频网站在线| 午夜美女福利小视频| AV无码一区二区三区不卡| 欧美综合婷婷欧美综合| 男人的天堂一区二区在线观看| av破解版在线观看| 亚洲精品国产在线电影| 午夜精品久久久久久99热| 日韩欧美高清免费在线| jiuse91九色视频| 精品av国产一区二区三区四区| 美洲精品一二三产区区别| av一本二本在线观看| gay gay男男瑟瑟在线网站| 狠狠的往里顶撞h百合| 日本人妻少妇18—xx| 欧美va亚洲va天堂va| 在线观看911精品国产| 免费69视频在线看| 国产精品自偷自拍啪啪啪| 最新97国产在线视频| 青草青永久在线视频18| 中文字幕—97超碰网| 人妻少妇亚洲一区二区| 免费观看国产综合视频| 97人妻夜夜爽二区欧美极品| 激情五月婷婷免费视频| 日本一二三中文字幕| 色爱av一区二区三区| 偷拍自拍视频图片免费| 青娱乐最新视频在线| 老鸭窝日韩精品视频观看| 青青色国产视频在线| 狠狠的往里顶撞h百合| 亚洲国际青青操综合网站| 日本少妇在线视频大香蕉在线观看| 国产又粗又猛又爽又黄的视频在线| 亚洲1区2区3区精华液| ka0ri在线视频| 中文字幕乱码人妻电影| 一区二区三区四区视频在线播放| 国产三级精品三级在线不卡| 少妇深喉口爆吞精韩国| 午夜美女少妇福利视频| 中文字幕午夜免费福利视频| 中文字幕中文字幕人妻| 啊慢点鸡巴太大了啊舒服视频| 成人H精品动漫在线无码播放| 2021年国产精品自拍| yy6080国产在线视频| 18禁精品网站久久| 日本a级视频老女人| 亚洲av午夜免费观看| 青青草人人妻人人妻| 91色秘乱一区二区三区| 亚洲精品乱码久久久久久密桃明| 一区二区三区日本伦理| 又色又爽又黄又刺激av网站| 啊啊啊视频试看人妻| 午夜久久久久久久99| 综合激情网激情五月天| 桃色视频在线观看一区二区| 国产精品久久久久国产三级试频| 在线国产精品一区二区三区| 亚洲av天堂在线播放| 性生活第二下硬不起来| 国产精品探花熟女在线观看| 99亚洲美女一区二区三区| 久久久麻豆精亚洲av麻花| 亚洲国产最大av综合| 日韩人妻xxxxx| 动漫美女的小穴视频| 日本高清成人一区二区三区| 三级黄色亚洲成人av| 欧美性受xx黑人性猛交| 日韩欧美亚洲熟女人妻| 亚洲人成精品久久久久久久| 欧美精品免费aaaaaa| 无码国产精品一区二区高潮久久4 日韩欧美一级精品在线观看 | 国产亚洲四十路五十路| 日韩写真福利视频在线观看| 青草亚洲视频在线观看| 精品av久久久久久久| 亚洲综合另类欧美久久| 在线免费观看黄页视频| 2022国产综合在线干| 99精品视频之69精品视频| 老熟妇凹凸淫老妇女av在线观看| 亚洲午夜电影之麻豆| 最新国产精品拍在线观看| 天堂资源网av中文字幕| 亚洲av色香蕉一区二区三区| 亚洲欧美成人综合在线观看| 日韩精品电影亚洲一区| 免费男阳茎伸入女阳道视频| 日韩欧美在线观看不卡一区二区 | 久久这里只有精品热视频| 国产精品久久久久网| 亚洲午夜电影之麻豆| 国产刺激激情美女网站| 欧美精品一区二区三区xxxx| 激情国产小视频在线| 亚洲另类综合一区小说| 精品久久婷婷免费视频| 888亚洲欧美国产va在线播放| 大香蕉伊人国产在线| 啊啊好大好爽啊啊操我啊啊视频| 亚洲一级av无码一级久久精品| 男人天堂av天天操| 成人在线欧美日韩国产| 久久人人做人人妻人人玩精品vr | av亚洲中文天堂字幕网| 天天日天天添天天爽| 大鸡巴操娇小玲珑的女孩逼| 成人24小时免费视频| 黄片色呦呦视频免费看| 天天日天天添天天爽| 1区2区3区4区视频在线观看| 欧美视频不卡一区四区| 人妻丝袜诱惑我操她视频| 人妻少妇一区二区三区蜜桃| 欧美老妇精品另类不卡片| 亚洲午夜伦理视频在线| 国产又粗又黄又硬又爽| 超碰公开大香蕉97| 国产白袜脚足J棉袜在线观看| 久久热久久视频在线观看| 2012中文字幕在线高清| 欧洲精品第一页欧洲精品亚洲| 激情色图一区二区三区| 亚洲熟色妇av日韩熟色妇在线 | 加勒比视频在线免费观看| 在线免费观看视频一二区| 午夜免费体验区在线观看| 成人网18免费视频版国产| 久久热这里这里只有精品| 91www一区二区三区| 免费成人va在线观看| 亚洲国产中文字幕啊啊啊不行了 | 日本中文字幕一二区视频| 9l人妻人人爽人人爽| 亚洲一区av中文字幕在线观看| 人人妻人人人操人人人爽| 日本阿v视频在线免费观看| av一本二本在线观看| 瑟瑟视频在线观看免费视频| 一级黄片久久久久久久久| 97a片免费在线观看| 大白屁股精品视频国产| 一区二区三区久久中文字幕| 久久综合老鸭窝色综合久久| 国产福利小视频免费观看| 精品美女久久久久久| 日韩不卡中文在线视频网站| 久草视频福利在线首页| 亚洲精品ww久久久久久| 亚洲人一区二区中文字幕| 亚洲欧美国产麻豆综合| 欧美viboss性丰满| 后入美女人妻高清在线| 日本啪啪啪啪啪啪啪| 国产午夜亚洲精品不卡在线观看| 亚洲一区二区三区精品乱码| 亚洲中文字幕人妻一区| 欧美男人大鸡吧插女人视频| 精品首页在线观看视频| 大鸡巴操b视频在线| 欧美黑人性暴力猛交喷水| 一区二区三区欧美日韩高清播放| 亚洲一区久久免费视频| 春色激情网欧美成人| 青青青青青青青青青青草青青| 揄拍成人国产精品免费看视频| 成人动漫大肉棒插进去视频| 91在线免费观看成人| 97少妇精品在线观看| 天天射,天天操,天天说| 啊啊好慢点插舔我逼啊啊啊视频| 99人妻视频免费在线| 超级碰碰在线视频免费观看| 伊人成人综合开心网| 淫秽激情视频免费观看| 动漫精品视频在线观看| 美洲精品一二三产区区别| 哥哥姐姐综合激情小说| 国产超码片内射在线| 91老师蜜桃臀大屁股| 亚洲欧美国产综合777| 99久久激情婷婷综合五月天| 青青尤物在线观看视频网站 | 精品suv一区二区69| 亚洲 国产 成人 在线| 日韩人妻xxxxx| 无码国产精品一区二区高潮久久4| 丰满少妇人妻xxxxx| 老司机免费视频网站在线看| 国产成人自拍视频在线免费观看| 欧美成人综合色在线噜噜| 骚货自慰被发现爆操| 天天日天天敢天天干| 欧美黑人巨大性xxxxx猛交| 欧美精品国产综合久久| 国产亚洲国产av网站在线| 中文字幕免费福利视频6| yy6080国产在线视频| 视频一区二区三区高清在线| 熟女91pooyn熟女| 91亚洲精品干熟女蜜桃频道| 丰满的子国产在线观看| 同居了嫂子在线播高清中文| 亚洲精品麻豆免费在线观看| av网站色偷偷婷婷网男人的天堂| sejizz在线视频| 国产高清女主播在线| 亚洲一区二区三区久久午夜| 初美沙希中文字幕在线| 久久尻中国美女视频| 亚洲av琪琪男人的天堂| 韩国爱爱视频中文字幕| 天天日天天干天天要| 中文字母永久播放1区2区3区| 国产一区二区三免费视频| 亚洲福利精品福利精品福利| 国产亚洲欧美另类在线观看| 久久久91蜜桃精品ad| 亚洲美女高潮喷浆视频| 免费观看丰满少妇做受| 国产精品自拍视频大全| 日韩欧美一级黄片亚洲| 视频一区二区综合精品| 哥哥姐姐综合激情小说| 精品高跟鞋丝袜一区二区| 亚洲少妇高潮免费观看| 天天日天天鲁天天操| 日本男女操逼视频免费看| 国产清纯美女al在线| 在线视频自拍第三页| 欧美特色aaa大片| 欧美韩国日本国产亚洲| 欧美老妇精品另类不卡片| 大鸡巴插入美女黑黑的阴毛| 青青在线视频性感少妇和隔壁黑丝| 偷拍自拍亚洲视频在线观看| 精品美女福利在线观看| 日本精品视频不卡一二三| 欧美地区一二三专区| 人人在线视频一区二区| 日韩视频一区二区免费观看| 亚洲伊人av天堂有码在线| 极品性荡少妇一区二区色欲| 无码国产精品一区二区高潮久久4| 五月天色婷婷在线观看视频免费| 日韩特级黄片高清在线看| 又色又爽又黄的美女裸体| 亚洲精品福利网站图片| 国产一区成人在线观看视频| 国产老熟女伦老熟妇ⅹ| 91精品啪在线免费| 亚洲精品欧美日韩在线播放| 骚货自慰被发现爆操| 蜜桃臀av蜜桃臀av| 把腿张开让我插进去视频| 日本av熟女在线视频| 日韩欧美国产一区不卡| 久久久久国产成人精品亚洲午夜| 唐人色亚洲av嫩草| 黄色中文字幕在线播放| 四川乱子伦视频国产vip| 在线观看成人国产电影| 综合精品久久久久97| 黄片色呦呦视频免费看| 天堂v男人视频在线观看| 色婷婷精品大在线观看| 日韩av有码一区二区三区4 | 中文字幕免费福利视频6| 日本精品美女在线观看| 精品av久久久久久久| 岛国毛片视频免费在线观看| 天天干天天操天天爽天天摸| 亚洲无码一区在线影院| 黄片三级三级三级在线观看| 男人的天堂av日韩亚洲| 在线视频这里只有精品自拍| 不卡精品视频在线观看| 和邻居少妇愉情中文字幕| 都市家庭人妻激情自拍视频| 最新日韩av传媒在线| 在线视频这里只有精品自拍| www,久久久,com| 亚洲国际青青操综合网站| 国产aⅴ一线在线观看| 亚洲另类在线免费观看| 色在线观看视频免费的| 初美沙希中文字幕在线| 在线免费观看日本片| 亚洲高清视频在线不卡| 中国视频一区二区三区| 99精品视频在线观看免费播放 | 中国无遮挡白丝袜二区精品| 日日操夜夜撸天天干| 成人高清在线观看视频| av完全免费在线观看av| 色呦呦视频在线观看视频| 免费无码人妻日韩精品一区二区| 最近中文2019年在线看| 91极品大一女神正在播放| av中文字幕在线观看第三页| 97超碰人人搞人人| 青青青青青手机视频| 中文字幕一区二区亚洲一区| 国产精品久久久久国产三级试频| 亚洲国产成人av在线一区| 大香蕉日本伊人中文在线| 午夜精品亚洲精品五月色| 午夜精品一区二区三区4| 大学生A级毛片免费视频| 极品丝袜一区二区三区| 一本一本久久a久久精品综合不卡| 久久一区二区三区人妻欧美| 欧美日韩熟女一区二区三区| 黄色片年轻人在线观看| 亚洲国产欧美国产综合在线| 91福利视频免费在线观看| 天天日天天干天天插舔舔| 亚洲av日韩精品久久久久久hd| 精品人人人妻人人玩日产欧| 在线观看911精品国产| 毛片一级完整版免费| 91精品综合久久久久3d动漫| 91精品激情五月婷婷在线| 91‖亚洲‖国产熟女| 大香蕉大香蕉大香蕉大香蕉大香蕉 | 2020久久躁狠狠躁夜夜躁| 精品国产亚洲av一淫| 欧美成人一二三在线网| 亚洲变态另类色图天堂网| 3D动漫精品啪啪一区二区下载| 日本熟妇丰满厨房55| 亚洲欧美另类自拍偷拍色图| 制丝袜业一区二区三区| 狍和女人的王色毛片| 成人H精品动漫在线无码播放| 青青草国内在线视频精选| 欧美日韩v中文在线| 久久久久久性虐视频| 午夜美女少妇福利视频| 888欧美视频在线| 精品老妇女久久9g国产| 人妻久久无码中文成人| 国产精品人妻一区二区三区网站| 天天通天天透天天插| 2021年国产精品自拍| 超黄超污网站在线观看| 动漫av网站18禁| 日本男女操逼视频免费看| 久精品人妻一区二区三区| 精品av国产一区二区三区四区| 大黑人性xxxxbbbb| 青青青青青操视频在线观看| 成人影片高清在线观看| 日韩精品电影亚洲一区| 午夜精品福利一区二区三区p| 中文字幕日本人妻中出| 午夜国产福利在线观看| 夜鲁夜鲁狠鲁天天在线| 2022国产精品视频| 夜夜操,天天操,狠狠操| 98视频精品在线观看| 午夜青青草原网在线观看| 综合精品久久久久97| 激情小视频国产在线| 亚洲精品国产综合久久久久久久久| av天堂加勒比在线| 亚洲午夜在线视频福利| 中文字幕日韩91人妻在线| 91精品免费久久久久久| 国产在线91观看免费观看| 99久久成人日韩欧美精品| 国产真实灌醉下药美女av福利| 欧美精品伦理三区四区| 夫妻在线观看视频91| 中文字幕日韩91人妻在线| 亚洲欧美另类自拍偷拍色图| 久草视频 久草视频2| 天堂av狠狠操蜜桃| 换爱交换乱高清大片| 亚洲 色图 偷拍 欧美| 精品亚洲中文字幕av| 亚洲国产欧美国产综合在线| 免费高清自慰一区二区三区网站 | 在线观看日韩激情视频| 插逼视频双插洞国产操逼插洞| 亚洲另类图片蜜臀av| 亚洲av成人网在线观看| 成人精品在线观看视频| 看一级特黄a大片日本片黑人| 岛国一区二区三区视频在线| 漂亮 人妻被中出中文| 国产麻豆乱子伦午夜视频观看| 男生舔女生逼逼视频| 日韩影片一区二区三区不卡免费| 国产美女精品福利在线| 91亚洲精品干熟女蜜桃频道| 青青青青视频在线播放| 大香蕉福利在线观看| 久久综合老鸭窝色综合久久| 18禁网站一区二区三区四区| 久久亚洲天堂中文对白| 午夜毛片不卡在线看| 青娱乐蜜桃臀av色| 黑人巨大的吊bdsm| 欧美女同性恋免费a| 亚洲第一伊人天堂网| 欧美精品国产综合久久| 自拍偷拍 国产资源| 婷婷综合亚洲爱久久| 99精品视频之69精品视频 | 日韩特级黄片高清在线看| 白白操白白色在线免费视频 | 欧美视频不卡一区四区| 在线免费观看欧美小视频| 亚洲国产成人最新资源| 99热国产精品666| 国产精品久久综合久久| 国产成人精品一区在线观看 | 男生舔女生逼逼的视频| 午夜福利人人妻人人澡人人爽 | 日韩无码国产精品强奸乱伦| 啪啪啪18禁一区二区三区| 首之国产AV医生和护士小芳| 欧美精产国品一二三产品价格| 一区二区三区四区视频| 摧残蹂躏av一二三区| 黄色的网站在线免费看| 欧美精品黑人性xxxx| 天天干天天插天天谢| 亚洲熟女女同志女同| 插逼视频双插洞国产操逼插洞| 在线网站你懂得老司机| 在线亚洲天堂色播av电影| 内射久久久久综合网| 人人妻人人人操人人人爽| 青青青青视频在线播放| 中文字幕高清免费在线人妻| 大胸性感美女羞爽操逼毛片| 免费高清自慰一区二区三区网站| 久久99久久99精品影院| 国产janese在线播放| 加勒比视频在线免费观看| 亚洲国产第一页在线观看| 直接观看免费黄网站| 2021天天色天天干| 欧美精品黑人性xxxx| 日本性感美女写真视频| 任你操任你干精品在线视频| 2022天天干天天操| 日韩欧美一级精品在线观看| 漂亮 人妻被中出中文| 日韩人妻xxxxx| 国产精品自拍在线视频| 日韩欧美一级黄片亚洲| 青青青青青操视频在线观看| 欧美一区二区三区高清不卡tv| 国产激情av网站在线观看| 天天色天天操天天舔| 亚洲中文字幕乱码区| 国产美女精品福利在线| 日韩欧美在线观看不卡一区二区| 2018在线福利视频| 欧美亚洲自偷自拍 在线| 夜鲁夜鲁狠鲁天天在线| 欧美区一区二区三视频| 天天日天天做天天日天天做| 亚洲少妇高潮免费观看| 成人免费公开视频无毒| 久久免看30视频口爆视频| 国产午夜无码福利在线看| 午夜激情高清在线观看| 亚洲av日韩高清hd| 又粗又长 明星操逼小视频| 亚洲青青操骚货在线视频| 欧美色婷婷综合在线| 黄色大片男人操女人逼| 91国产资源在线视频| 91国语爽死我了不卡| 99re久久这里都是精品视频| av中文字幕在线导航| 一区二区在线视频中文字幕| 51国产偷自视频在线播放| tube69日本少妇| 青青青青青青草国产| 中文字幕一区二区亚洲一区| av在线免费中文字幕| 国产白嫩美女一区二区| 亚洲中文字幕综合小综合| 亚洲麻豆一区二区三区| 欲乱人妻少妇在线视频裸| 国产91精品拍在线观看| 欧美 亚洲 另类综合| 岳太深了紧紧的中文字幕| 亚洲高清视频在线不卡| 激情啪啪啪啪一区二区三区| 自拍偷拍,中文字幕| 亚洲精品国产久久久久久| 在线免费观看欧美小视频| 日韩欧美国产一区ab| 97人妻人人澡爽人人精品| 老鸭窝在线观看一区| 内射久久久久综合网| 91啪国自产中文字幕在线| 天堂av在线最新版在线| 91色九色porny| 一区二区三区欧美日韩高清播放| 国产精品三级三级三级| 欧美日本国产自视大全| 午夜在线观看一区视频| 偷青青国产精品青青在线观看| 91麻豆精品秘密入口在线观看| 自拍偷拍 国产资源| 成人18禁网站在线播放| 亚洲国际青青操综合网站| 熟妇一区二区三区高清版| 国产麻豆乱子伦午夜视频观看| 亚洲无码一区在线影院| 亚洲熟妇久久无码精品| 啊啊好大好爽啊啊操我啊啊视频| 亚洲在线免费h观看网站| 亚洲综合另类欧美久久| 任你操视频免费在线观看| 婷婷五月亚洲综合在线| 中文字幕成人日韩欧美| 午夜福利人人妻人人澡人人爽| 午夜美女少妇福利视频| 后入美女人妻高清在线| 国产精品精品精品999| 好男人视频在线免费观看网站| 欧美aa一级一区三区四区| 亚洲精品乱码久久久本| 在线制服丝袜中文字幕| 亚洲综合色在线免费观看| 国产精品视频一区在线播放| 亚洲一级av无码一级久久精品| 999九九久久久精品| 在线观看911精品国产| 偷拍自拍国产在线视频| 亚洲另类图片蜜臀av| 五十路av熟女松本翔子| 青青青艹视频在线观看| 亚洲成高清a人片在线观看| 中文字幕中文字幕人妻| 亚洲免费国产在线日韩| 久草视频 久草视频2| 免费大片在线观看视频网站| 美女大bxxxx内射| 亚洲一级美女啪啪啪| 亚洲成人av一区在线| 天天干天天爱天天色| 天天日夜夜干天天操| 91精品激情五月婷婷在线| 青青尤物在线观看视频网站| 91大神福利视频网| 午夜精品一区二区三区更新| 色综合久久无码中文字幕波多| 端庄人妻堕落挣扎沉沦| 91麻豆精品秘密入口在线观看| 二区中出在线观看老师| 国产片免费观看在线观看| 黄片三级三级三级在线观看| 日本xx片在线观看| 国产精品久久9999| 熟女人妻在线中出观看完整版| 亚洲成人激情av在线| 日本av高清免费网站| 日韩av大胆在线观看| 免费观看国产综合视频| 日本裸体熟妇区二区欧美| 激情人妻校园春色亚洲欧美 | 亚洲午夜伦理视频在线| 在线观看免费视频色97| 成人免费公开视频无毒| 精彩视频99免费在线| 亚洲成人熟妇一区二区三区| 特一级特级黄色网片| gogo国模私拍视频| 999九九久久久精品| 黑人大几巴狂插日本少妇| 亚洲国产在线精品国偷产拍| 男人天堂av天天操| 黄色大片免费观看网站| 国产成人精品久久二区91| 老司机福利精品视频在线| 91免费黄片可看视频| 大白屁股精品视频国产| 中文字幕高清免费在线人妻| 中文字幕最新久久久| 天天操夜夜操天天操天天操| 最新日韩av传媒在线| 日韩欧美在线观看不卡一区二区 | av高潮迭起在线观看| chinese国产盗摄一区二区 | 伊人成人综合开心网| 免费观看成年人视频在线观看| 中文字幕第一页国产在线| 中文字幕av第1页中文字幕| 日本av高清免费网站| 美女小视频网站在线| 成人亚洲国产综合精品| 亚洲欧美精品综合图片小说| 日韩熟女av天堂系列| 美女福利视频导航网站| 91亚洲国产成人精品性色| 亚洲av色香蕉一区二区三区| 亚洲天堂精品福利成人av| 女蜜桃臀紧身瑜伽裤| 国产精品福利小视频a| 动漫av网站18禁| 国产一级精品综合av| 成人色综合中文字幕| 男人的天堂一区二区在线观看| 东京干手机福利视频| 黄色黄色黄片78在线| 免费看美女脱光衣服的视频| 中文字幕人妻熟女在线电影| 中文字幕—97超碰网| 亚洲变态另类色图天堂网| 一区二区在线视频中文字幕| 午夜精品久久久久久99热| 福利午夜视频在线观看| 91免费观看在线网站| 五色婷婷综合狠狠爱| 99热99re在线播放| 日韩一个色综合导航| 国产精品自拍偷拍a| 蜜桃久久久久久久人妻| 国产高清97在线观看视频| 国产变态另类在线观看| 中文字幕人妻熟女在线电影| sejizz在线视频| 国产成人午夜精品福利| 97人人妻人人澡人人爽人人精品| 精品91高清在线观看| 国产美女精品福利在线| 中文字幕一区二 区二三区四区| 成人福利视频免费在线| 亚洲人妻30pwc| 91久久国产成人免费网站| 性色av一区二区三区久久久| 亚洲第17页国产精品| 欧美天堂av无线av欧美| 91一区精品在线观看| 亚洲 中文 自拍 另类 欧美| 精品亚洲国产中文自在线| 成人资源在线观看免费官网| 丝袜肉丝一区二区三区四区在线看| 欧美老鸡巴日小嫩逼| 1769国产精品视频免费观看| 一区二区久久成人网| 国产av福利网址大全| 涩爱综合久久五月蜜臀| 黑人乱偷人妻中文字幕| 天堂av中文在线最新版| 国产精品黄片免费在线观看| 强行扒开双腿猛烈进入免费版| 2012中文字幕在线高清| 福利午夜视频在线观看| 天天日天天鲁天天操| 亚洲精品无码久久久久不卡| 亚洲va天堂va国产va久| 国产精品系列在线观看一区二区 | 天天做天天干天天舔| 国产高清精品一区二区三区| 最新中文字幕免费视频| 免费黄页网站4188| 中文字幕在线观看极品视频| 97少妇精品在线观看| 新婚人妻聚会被中出| 中文字幕在线乱码一区二区| 日韩无码国产精品强奸乱伦| 久久久久久久精品成人热| 天天日天天鲁天天操| 成人国产激情自拍三区| 精品91自产拍在线观看一区| 日本脱亚入欧是指什么| 大鸡吧插逼逼视频免费看 | 久久久噜噜噜久久熟女av| 男人插女人视频网站| 大胸性感美女羞爽操逼毛片| av成人在线观看一区| 国产又粗又硬又大视频| 亚洲码av无色中文| 日韩伦理短片在线观看| 国产亚洲欧美另类在线观看| 中文字幕午夜免费福利视频| 亚洲午夜福利中文乱码字幕| 欧美香蕉人妻精品一区二区| 亚洲免费视频欧洲免费视频 | 中国产一级黄片免费视频播放| av老司机亚洲一区二区| 天天干夜夜操天天舔| 一区二区视频视频视频| 亚洲va国产va欧美va在线| 午夜久久久久久久99| rct470中文字幕在线| 超碰在线观看免费在线观看| 日韩精品中文字幕福利| 国产精品视频男人的天堂| 国产va精品免费观看 | 日本www中文字幕| 亚洲综合乱码一区二区| 久久久精品精品视频视频| 国产精品亚洲在线观看| 亚洲va欧美va人人爽3p| 日韩欧美国产精品91| 视频一区二区在线免费播放| 久久久久只精品国产三级| 人妻激情图片视频小说| 老司机福利精品免费视频一区二区 | 国产性色生活片毛片春晓精品| 美女张开两腿让男人桶av| 一区二区三区美女毛片| 欧美成人黄片一区二区三区| 亚洲美女自偷自拍11页| 日本少妇人妻xxxxx18| 二区中出在线观看老师| 欧美日韩在线精品一区二区三| 亚洲成人熟妇一区二区三区| 亚洲 欧美 精品 激情 偷拍 | 久久热久久视频在线观看| 日韩三级电影华丽的外出| 传媒在线播放国产精品一区 | 国产精品三级三级三级| 中文字幕最新久久久| 好太好爽好想要免费| 国产精品自拍视频大全| 99婷婷在线观看视频| 中文字幕一区二区亚洲一区| 国产美女一区在线观看| 国产实拍勾搭女技师av在线| 一区二区麻豆传媒黄片 | 大黑人性xxxxbbbb| 白嫩白嫩美女极品国产在线观看| 日本丰满熟妇大屁股久久| 看一级特黄a大片日本片黑人| 丰满的继坶3中文在线观看| 亚洲精品无码色午夜福利理论片| 精品人妻每日一部精品| 成人资源在线观看免费官网| 任你操视频免费在线观看| 大鸡巴操娇小玲珑的女孩逼| 亚洲人一区二区中文字幕| 成人H精品动漫在线无码播放| 色综合久久久久久久久中文| 91快播视频在线观看| 日本一二三区不卡无| 亚洲在线免费h观看网站| 夜色福利视频在线观看| 2018在线福利视频| 三级黄色亚洲成人av| 成人av免费不卡在线观看| sw137 中文字幕 在线| 日本黄色特一级视频| 天天色天天操天天舔| 天堂av狠狠操蜜桃| 亚洲Av无码国产综合色区| 女同性ⅹxx女同hd| 亚洲精品麻豆免费在线观看| 天堂av在线播放免费| 国产在线拍揄自揄视频网站| 伊人成人综合开心网| 护士小嫩嫩又紧又爽20p| 老有所依在线观看完整版| 97香蕉碰碰人妻国产樱花| 欧美精品 日韩国产| 日本一二三区不卡无| 日韩精品啪啪视频一道免费| 久久久久久久一区二区三| 午夜的视频在线观看| 快点插进来操我逼啊视频| 小泽玛利亚视频在线观看| 日日夜夜狠狠干视频| 婷婷久久久综合中文字幕| 免费男阳茎伸入女阳道视频| 久久久久久久久久久久久97| 欧美viboss性丰满| 日本丰满熟妇BBXBBXHD| 亚洲女人的天堂av| 国产成人无码精品久久久电影| 91she九色精品国产| 国产又粗又黄又硬又爽| 国产+亚洲+欧美+另类| 熟女国产一区亚洲中文字幕| 日本韩国亚洲综合日韩欧美国产 | 中文字幕av熟女人妻| 六月婷婷激情一区二区三区| 国产精品人久久久久久| 日本裸体熟妇区二区欧美| 91免费福利网91麻豆国产精品 | 少妇露脸深喉口爆吞精| 亚洲福利精品视频在线免费观看| 亚洲成人av一区在线| 亚洲天天干 夜夜操| 动漫美女的小穴视频| 国产麻豆91在线视频| 欧美专区第八页一区在线播放| 少妇一区二区三区久久久| 少妇被强干到高潮视频在线观看| 18禁精品网站久久| 专门看国产熟妇的网站| 女警官打开双腿沦为性奴| 欧美va亚洲va天堂va| 亚洲欧美一区二区三区电影| 中文字幕人妻熟女在线电影| 久久久久只精品国产三级| 91色九色porny| 女同久久精品秋霞网| 婷婷六月天中文字幕| 影音先锋女人av噜噜色| 人妻少妇亚洲精品中文字幕| 午夜婷婷在线观看视频| 免费观看污视频网站| 日韩三级电影华丽的外出| 黄色成人在线中文字幕| 日本熟女50视频免费| 欧美第一页在线免费观看视频| 国产亚洲视频在线二区| 亚洲特黄aaaa片| 91麻豆精品秘密入口在线观看| 亚洲一区二区激情在线| 国产亚洲精品视频合集| 国产性生活中老年人视频网站| 一区二区三区四区中文| 2020久久躁狠狠躁夜夜躁| 55夜色66夜色国产精品站| 日韩人妻丝袜中文字幕| 国际av大片在线免费观看| 水蜜桃一区二区三区在线观看视频| 精品一区二区亚洲欧美| 青青色国产视频在线| 97年大学生大白天操逼| 天天日天天摸天天爱| 一区二区视频在线观看免费观看| 美女操逼免费短视频下载链接| 经典国语激情内射视频| 亚洲国产成人无码麻豆艾秋| 亚洲精品ww久久久久久| av新中文天堂在线网址| 欧美熟妇一区二区三区仙踪林| 哥哥姐姐综合激情小说| 最新97国产在线视频| 亚洲国产中文字幕啊啊啊不行了 | 91老师蜜桃臀大屁股| 日本特级片中文字幕| 欧美亚洲自偷自拍 在线| 精品久久久久久高潮| 这里只有精品双飞在线播放| 91亚洲国产成人精品性色| 日本高清在线不卡一区二区| 美女张开两腿让男人桶av| 抽查舔水白紧大视频| 国产日本精品久久久久久久| 在线观看成人国产电影| 最新中文字幕免费视频| 国产实拍勾搭女技师av在线| 粉嫩av懂色av蜜臀av| 福利午夜视频在线观看| 中文字幕一区的人妻欧美日韩| 在线观看视频 你懂的| 亚洲精品在线资源站| 青青青青爽手机在线| 久久亚洲天堂中文对白| 免费男阳茎伸入女阳道视频| 色呦呦视频在线观看视频| 国产精品人妻熟女毛片av久| 极品性荡少妇一区二区色欲| 特级欧美插插插插插bbbbb| 91福利在线视频免费观看| 日韩精品电影亚洲一区| 国产在线自在拍91国语自产精品| 国产亚洲欧美45p| 少妇人妻100系列| 日韩激情文学在线视频| 1769国产精品视频免费观看| 欧美精品免费aaaaaa| 又粗又长 明星操逼小视频| 五十路av熟女松本翔子| 视频一区 二区 三区 综合| 欧美老妇精品另类不卡片| 国产va在线观看精品| 日本黄色三级高清视频| 97精品人妻一区二区三区精品| 丰满少妇人妻xxxxx| 欧美一区二区三区啪啪同性| 五十路熟女人妻一区二| 51国产成人精品视频| 国产综合高清在线观看| 日本性感美女写真视频| 38av一区二区三区| 亚洲国产免费av一区二区三区| 国产亚洲欧美另类在线观看| 亚洲麻豆一区二区三区| 日本人妻欲求不满中文字幕| 日本成人不卡一区二区| 91精品激情五月婷婷在线| 亚洲精品午夜aaa久久| 黄片三级三级三级在线观看| 99久久99一区二区三区| 98视频精品在线观看| 欧美麻豆av在线播放| 亚洲av男人天堂久久| 日韩a级精品一区二区| 色综合色综合色综合色| 精品视频国产在线观看| 国产精品福利小视频a| 黄色录像鸡巴插进去| 蜜桃视频在线欧美一区| 亚洲蜜臀av一区二区三区九色| 家庭女教师中文字幕在线播放 | 男生舔女生逼逼的视频| 亚洲一区二区久久久人妻| 超碰中文字幕免费观看| 午夜美女少妇福利视频| 国产精品久久久久久久女人18| 日韩精品中文字幕播放| 美女av色播在线播放| av一区二区三区人妻| 香蕉aⅴ一区二区三区| 啪啪啪啪啪啪啪啪啪啪黄色| 日韩精品中文字幕播放| 2021最新热播中文字幕| 亚洲推理片免费看网站| 和邻居少妇愉情中文字幕| 中文字幕AV在线免费看 | 久久久精品欧洲亚洲av| eeuss鲁片一区二区三区| 中文字幕免费在线免费| 国产精品国产三级麻豆| 国产日韩精品电影7777| 精品黑人巨大在线一区| 天天日天天摸天天爱| 亚洲区欧美区另类最新章节| 嫩草aⅴ一区二区三区| 男生用鸡操女生视频动漫| 亚洲中文字幕国产日韩| 国产午夜亚洲精品不卡在线观看| 成人综合亚洲欧美一区| 2020久久躁狠狠躁夜夜躁| 人妻少妇一区二区三区蜜桃| eeuss鲁片一区二区三区| 可以免费看的www视频你懂的 | 国产janese在线播放| 中国无遮挡白丝袜二区精品| 欧美日韩国产一区二区三区三州| 久久精品在线观看一区二区| 亚洲Av无码国产综合色区| 91成人精品亚洲国产| 人妻少妇av在线观看| 亚洲成人激情av在线| 中文字幕在线一区精品| 美女大bxxxx内射| 国产精品久久久久久久女人18| 青青草原网站在线观看| 中文字幕午夜免费福利视频| 最新97国产在线视频| 欧洲亚洲欧美日韩综合| 综合激情网激情五月天| 亚洲蜜臀av一区二区三区九色 | 久久精品在线观看一区二区| 欧美亚洲少妇福利视频| 精品老妇女久久9g国产| 色婷婷综合激情五月免费观看| 午夜国产福利在线观看| 久久这里只有精品热视频| 国产视频网站一区二区三区| 唐人色亚洲av嫩草| 成年人免费看在线视频| 日美女屁股黄邑视频| 久久精品国产23696| 五月天色婷婷在线观看视频免费| 国产黄色大片在线免费播放| 精品人人人妻人人玩日产欧| 在线免费观看99视频| 日韩一区二区三区三州| 人妻熟女中文字幕aⅴ在线| 久久艹在线观看视频| 国产丰满熟女成人视频| 一二三区在线观看视频| 亚洲乱码中文字幕在线| 亚洲一区制服丝袜美腿| 成人性黑人一级av| 成人av天堂丝袜在线观看| 色哟哟国产精品入口| 欧亚乱色一区二区三区| 伊人综合免费在线视频| 视频久久久久久久人妻| 日韩人妻丝袜中文字幕| 福利视频网久久91| 自拍偷拍一区二区三区图片 | 98精产国品一二三产区区别| 国产一区二区在线欧美| 国产中文精品在线观看| 人人人妻人人澡人人| 亚洲一级 片内射视正片| AV天堂一区二区免费试看| 欧美一区二区三区高清不卡tv| 午夜大尺度无码福利视频| 在线观看av观看av| 久久艹在线观看视频| 韩国一级特黄大片做受| 午夜精品亚洲精品五月色| 亚洲精品欧美日韩在线播放| 爱有来生高清在线中文字幕| 九一传媒制片厂视频在线免费观看| 很黄很污很色的午夜网站在线观看| 国产成人午夜精品福利| 干逼又爽又黄又免费的视频| 夜鲁夜鲁狠鲁天天在线| 色综合久久五月色婷婷综合| 日韩精品中文字幕福利| 中文字幕之无码色多多| 999久久久久999| 99热国产精品666| 老熟妇xxxhd老熟女| 天天操天天干天天日狠狠插 | xxx日本hd高清| 国产在线观看免费人成短视频| 免费十精品十国产网站| 天天日天天敢天天干| 视频 国产 精品 熟女 | 一色桃子久久精品亚洲 | 99国产精品窥熟女精品| 精品一区二区三区在线观看| 国产精品系列在线观看一区二区|