国产无遮挡裸体免费直播视频,久久精品国产蜜臀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)論

福利在线视频网址导航| 91av中文视频在线| 喷水视频在线观看这里只有精品 | 含骚鸡巴玩逼逼视频| 91久久人澡人人添人人爽乱| 欧美国产亚洲中英文字幕| 婷婷久久一区二区字幕网址你懂得| 日曰摸日日碰夜夜爽歪歪| 97人妻色免费视频| 在线国产精品一区二区三区| 欲满人妻中文字幕在线| 亚洲 国产 成人 在线| 天天日天天透天天操| 丝袜美腿欧美另类 中文字幕| 黄色成年网站午夜在线观看| 91亚洲国产成人精品性色| 成人性爱在线看四区| 一区二区三区四区五区性感视频| 欧美精品激情在线最新观看视频| 老鸭窝在线观看一区| 91快播视频在线观看| 涩爱综合久久五月蜜臀| 综合页自拍视频在线播放| 亚洲激情av一区二区| 大香蕉大香蕉在线看| 国产大学生援交正在播放| 午夜在线观看一区视频| 亚洲中文字幕校园春色| 成人蜜桃美臀九一一区二区三区| 2022中文字幕在线| 青青社区2国产视频| 青青青青青操视频在线观看| 亚洲激情av一区二区| 亚洲少妇人妻无码精品| 精品黑人一区二区三区久久国产 | 久久午夜夜伦痒痒想咳嗽P| 欧美一区二区三区激情啪啪啪 | 亚洲av人人澡人人爽人人爱| 天堂av在线官网中文| 国产亚洲视频在线观看| 激情色图一区二区三区| 女生被男生插的视频网站| 亚洲综合在线观看免费| 扒开让我视频在线观看| asmr福利视频在线观看| 欧美麻豆av在线播放| 黑人解禁人妻叶爱071| 97超碰国语国产97超碰| 亚洲欧美一区二区三区电影| 沙月文乃人妻侵犯中文字幕在线| 欧美视频综合第一页| 岳太深了紧紧的中文字幕| 五十路熟女人妻一区二| 国产自拍黄片在线观看| 日韩精品二区一区久久| 欧美久久一区二区伊人| 毛茸茸的大外阴中国视频| 欧美爆乳肉感大码在线观看| 日本性感美女三级视频| av在线shipin| 88成人免费av网站| 日本美女性生活一级片| 日韩二区视频一线天婷婷五| 亚洲日产av一区二区在线| 中文字幕无码一区二区免费| 888欧美视频在线| 高清一区二区欧美系列| 日韩精品激情在线观看| 欧美男同性恋69视频| 亚洲人妻视频在线网| av在线shipin| 午夜国产免费福利av| 免费av岛国天堂网站| av手机在线观播放网站| 天天操天天爽天天干| 视频 一区二区在线观看| 人妻少妇精品久久久久久| 日本一本午夜在线播放| 精品av国产一区二区三区四区 | 国产三级影院在线观看| 欧美一级视频一区二区| 欧美一区二区三区啪啪同性| 啊慢点鸡巴太大了啊舒服视频| 国产又粗又硬又大视频| 日日爽天天干夜夜操| 国产黄色片蝌蚪九色91| 人妻少妇亚洲一区二区| 天天操天天射天天操天天天| 天天射,天天操,天天说| 91精品国产观看免费| 欧美另类重口味极品在线观看| 国产一区二区火爆视频| 国产一线二线三线的区别在哪| 91色秘乱一区二区三区| 亚洲精品 欧美日韩| 九九视频在线精品播放| 一区国内二区日韩三区欧美| 天天日天天操天天摸天天舔| 亚洲熟妇无码一区二区三区| 任我爽精品视频在线播放| 亚洲成人国产综合一区| 5528327男人天堂| 精品成人午夜免费看| 九色porny九色9l自拍视频| 国产欧美精品一区二区高清 | 亚洲成高清a人片在线观看| 夜鲁夜鲁狠鲁天天在线| 久久久久久性虐视频| 国产 在线 免费 精品| 天天干夜夜操啊啊啊| 边摸边做超爽毛片18禁色戒| 色花堂在线av中文字幕九九 | 91成人在线观看免费视频| 婷婷色中文亚洲网68| 经典国语激情内射视频| 国产精品久久久久久美女校花| 国产91久久精品一区二区字幕| 亚洲成高清a人片在线观看| 影音先锋女人av噜噜色| 国产一区成人在线观看视频| huangse网站在线观看| 视频在线亚洲一区二区| 欧美精品一区二区三区xxxx| 中文字幕在线欧美精品| 在线观看免费av网址大全| 免费人成黄页网站在线观看国产| 白嫩白嫩美女极品国产在线观看| 午夜免费体验区在线观看| 日本熟女精品一区二区三区| 天天做天天干天天操天天射| 久久一区二区三区人妻欧美| 大鸡巴插入美女黑黑的阴毛| 亚洲一级美女啪啪啪| 成人18禁网站在线播放| 性感美女诱惑福利视频| 天天想要天天操天天干| 老师让我插进去69AV| 欧洲亚洲欧美日韩综合| 999热精品视频在线| 天码人妻一区二区三区在线看 | 欧美日韩一区二区电影在线观看| 国产之丝袜脚在线一区二区三区 | 韩国一级特黄大片做受| 欧美精品免费aaaaaa| 亚洲欧美另类自拍偷拍色图| 国产三级影院在线观看| 91国内视频在线观看| 日韩视频一区二区免费观看| 99精品国产自在现线观看| 成人av久久精品一区二区| 硬鸡巴动态操女人逼视频| 欧美成人综合色在线噜噜| 欧美日韩高清午夜蜜桃大香蕉| 国产性色生活片毛片春晓精品| 亚洲特黄aaaa片| 大香蕉日本伊人中文在线| 亚洲蜜臀av一区二区三区九色 | 任你操任你干精品在线视频| 日美女屁股黄邑视频| 国产成人精品一区在线观看| 中文字幕av熟女人妻| 亚洲中文字幕综合小综合| 欧美日韩人妻久久精品高清国产 | 熟女俱乐部一二三区| 一本一本久久a久久精品综合不卡 亚洲另类综合一区小说 | 久久丁香花五月天色婷婷| av日韩在线观看大全| 国产精品国色综合久久| 视频在线免费观看你懂得| 色哟哟国产精品入口| 日本一区美女福利视频| 日韩国产乱码中文字幕| 老司机欧美视频在线看| 黄色大片男人操女人逼| 一区二区三区国产精选在线播放 | 精品美女在线观看视频在线观看| 黄片三级三级三级在线观看| 欧美日韩在线精品一区二区三| 国产精品系列在线观看一区二区| 只有精品亚洲视频在线观看| 小穴多水久久精品免费看| 一区二区在线视频中文字幕| 日本少妇人妻xxxxx18| 狠狠的往里顶撞h百合| 天天日天天干天天干天天日| 99热久久这里只有精品8| 日韩人妻在线视频免费| 一区二区三区精品日本| av资源中文字幕在线观看| 午夜青青草原网在线观看| 免费十精品十国产网站| 无码国产精品一区二区高潮久久4| 绝顶痉挛大潮喷高潮无码 | 天天躁夜夜躁日日躁a麻豆| 9l人妻人人爽人人爽| 55夜色66夜色国产精品站| 国产日韩一区二区在线看 | 在线播放国产黄色av| 在线观看av亚洲情色| 婷婷久久一区二区字幕网址你懂得| 国产日韩精品一二三区久久久| 91欧美在线免费观看| 中文字幕人妻一区二区视频 | 天堂中文字幕翔田av| 国产极品美女久久久久久| 99热99re在线播放| 亚洲日本一区二区久久久精品| 欧美特级特黄a大片免费| 白白操白白色在线免费视频| 偷拍自拍亚洲美腿丝袜| 日韩视频一区二区免费观看| 五十路av熟女松本翔子| 国产美女一区在线观看| 91色九色porny| 色噜噜噜噜18禁止观看| 亚洲午夜福利中文乱码字幕| 99久久激情婷婷综合五月天| 久久精品视频一区二区三区四区 | 亚洲丝袜老师诱惑在线观看| 无码精品一区二区三区人| 日韩加勒比东京热二区| 日日夜夜精品一二三| 美女小视频网站在线| 久久免看30视频口爆视频| 亚洲精品精品国产综合| 国产高清在线在线视频| 成年人的在线免费视频| 毛茸茸的大外阴中国视频| 蝴蝶伊人久久中文娱乐网| 欧洲精品第一页欧洲精品亚洲| 国产一级麻豆精品免费| 超黄超污网站在线观看| av天堂加勒比在线| 国产精品自拍在线视频| 亚洲图片偷拍自拍区| 污污小视频91在线观看| 超黄超污网站在线观看| 午夜毛片不卡免费观看视频| 精品久久久久久久久久久99| 免费在线看的黄网站| 国产日韩精品一二三区久久久| 欧美乱妇无乱码一区二区| 亚国产成人精品久久久| 少妇与子乱在线观看| 小穴多水久久精品免费看| 日韩人妻在线视频免费| 欧美 亚洲 另类综合| 99视频精品全部15| 中文字幕无码日韩专区免费| 黄色录像鸡巴插进去| 国产一线二线三线的区别在哪| 新婚人妻聚会被中出| 一区二区久久成人网| 边摸边做超爽毛片18禁色戒| 区一区二区三国产中文字幕| 日本免费一级黄色录像| 色呦呦视频在线观看视频| 日韩av有码一区二区三区4| 97年大学生大白天操逼| 在线免费91激情四射 | 97精品成人一区二区三区| 青青青青青青青青青青草青青| 91在线视频在线精品3| 亚洲va欧美va人人爽3p| 国产内射中出在线观看| 国产日韩精品一二三区久久久| 中文字幕日本人妻中出| 一本久久精品一区二区| 国产黄色a级三级三级三级| 国产白袜脚足J棉袜在线观看| 久久精品国产23696| 91精品视频在线观看免费| 超鹏97历史在线观看| 午夜精品一区二区三区4| 天天日天天爽天天爽| 日本韩国免费一区二区三区视频| 亚洲 自拍 色综合图| 大鸡吧插入女阴道黄色片| 蜜桃色婷婷久久久福利在线| 一区二区免费高清黄色视频| 青青青国产免费视频| 国产污污污污网站在线| 久久这里有免费精品| 国产普通话插插视频| 午夜福利人人妻人人澡人人爽| 成人免费做爰高潮视频| 亚洲av极品精品在线观看| 成人国产小视频在线观看| 唐人色亚洲av嫩草| 国产高清女主播在线| 国产精品久久综合久久| 黄页网视频在线免费观看 | 粉嫩av蜜乳av蜜臀| av一本二本在线观看| 日本少妇人妻xxxxxhd| 传媒在线播放国产精品一区| 国产精选一区在线播放| 人妻丝袜精品中文字幕| 91色老99久久九九爱精品| 国产va精品免费观看 | www骚国产精品视频| 91极品新人『兔兔』精品新作| av男人天堂狠狠干| 二区中出在线观看老师| 绝顶痉挛大潮喷高潮无码 | 女人精品内射国产99| 亚洲国产美女一区二区三区软件| 亚洲 图片 欧美 图片| 又粗又硬又猛又爽又黄的| 欧美日本在线观看一区二区| 国产精品成人xxxx| 91久久精品色伊人6882| 孕妇奶水仑乱A级毛片免费看 | 青娱乐在线免费视频盛宴| 国产va在线观看精品| 九色视频在线观看免费| 欧美成人精品在线观看| 91精品免费久久久久久| av手机在线观播放网站| 91精品高清一区二区三区| jiujiure精品视频在线| 欧美成人小视频在线免费看| 青青青青在线视频免费观看| 干逼又爽又黄又免费的视频| 亚洲一区自拍高清免费视频| 国产极品精品免费视频 | 国产女人叫床高潮大片视频| av视屏免费在线播放| 天美传媒mv视频在线观看| 亚洲成人黄色一区二区三区| 日韩美女搞黄视频免费| 人妻另类专区欧美制服| 亚洲 图片 欧美 图片| 99热久久这里只有精品8| 欧美日韩高清午夜蜜桃大香蕉 | 亚洲美女美妇久久字幕组| 人人妻人人爽人人添夜| 国产成人精品久久二区91| 黄色成人在线中文字幕| 午夜在线观看岛国av,com| 麻豆性色视频在线观看| 国产av福利网址大全| 国产在线观看免费人成短视频| 国产夫妻视频在线观看免费| 免费在线黄色观看网站| 乱亲女秽乱长久久久| 午夜大尺度无码福利视频| 久久久久五月天丁香社区| 婷婷久久一区二区字幕网址你懂得| 78色精品一区二区三区| 欧美成人综合视频一区二区| 97青青青手机在线视频| 老司机99精品视频在线观看| 天天干夜夜操天天舔| 日本中文字幕一二区视频| 激情内射在线免费观看| 动漫精品视频在线观看| 成人性爱在线看四区| 任你操视频免费在线观看| 38av一区二区三区| 97资源人妻免费在线视频| 亚洲高清自偷揄拍自拍| 成人午夜电影在线观看 久久| 9l人妻人人爽人人爽| 天天操夜夜操天天操天天操| 青青青国产片免费观看视频| 中文字幕日韩人妻在线三区| 亚洲精品国产综合久久久久久久久 | 天天日夜夜干天天操| 天堂va蜜桃一区入口| 一色桃子久久精品亚洲 | 93精品视频在线观看| 成人午夜电影在线观看 久久| 欧美一区二区三区在线资源| 一区二区三区欧美日韩高清播放| 天天操天天爽天天干| 亚洲熟色妇av日韩熟色妇在线| 一区二区视频在线观看免费观看| 中文字幕之无码色多多| 日本免费午夜视频网站| 99re久久这里都是精品视频| 婷婷综合蜜桃av在线| 欧美日韩熟女一区二区三区| 91国内视频在线观看| 亚洲欧美成人综合视频| 五月激情婷婷久久综合网| 青青青视频自偷自拍38碰| 午夜精品福利一区二区三区p| 国产日韩一区二区在线看| 99热国产精品666| 国产熟妇一区二区三区av| 熟女人妻三十路四十路人妻斩| 久久久超爽一二三av| 国产中文字幕四区在线观看| 免费看国产又粗又猛又爽又黄视频| 国产麻豆剧果冻传媒app| 黄色在线观看免费观看在线| 四川乱子伦视频国产vip| 99精品免费观看视频| 国产精品福利小视频a| 午夜免费体验区在线观看| 丰满的子国产在线观看| 一级A一级a爰片免费免会员| 9色精品视频在线观看| 天天综合天天综合天天网| 3337p日本欧洲大胆色噜噜| 精品一区二区三区三区色爱| 一区二区麻豆传媒黄片| 欧美精品中文字幕久久二区| 视频一区二区综合精品| 亚洲人成精品久久久久久久| 4个黑人操素人视频网站精品91| 天天插天天狠天天操| 成人色综合中文字幕| 水蜜桃一区二区三区在线观看视频| 快插进小逼里大鸡吧视频| 精品久久久久久久久久久久人妻| 精品老妇女久久9g国产| 99re6热在线精品| 中文字幕在线乱码一区二区| 91精品国产综合久久久蜜| www天堂在线久久| 亚洲欧美精品综合图片小说| nagger可以指黑人吗| 风流唐伯虎电视剧在线观看| 亚洲精品无码色午夜福利理论片| 2022国产综合在线干| 99婷婷在线观看视频| 亚洲精品国偷自产在线观看蜜桃| 中文字幕网站你懂的| 视频一区 视频二区 视频| 自拍偷拍亚洲另类色图| 亚洲色偷偷综合亚洲AV伊人| 国产午夜亚洲精品不卡在线观看| 亚洲熟妇无码一区二区三区| 精品一区二区三区三区88| 免费观看丰满少妇做受| 精品国产成人亚洲午夜| 久久三久久三久久三久久| 护士小嫩嫩又紧又爽20p| av森泽佳奈在线观看| 99热久久极品热亚洲| 中文字幕第1页av一天堂网 | 青青色国产视频在线| 污污小视频91在线观看| 天堂av中文在线最新版| 国产成人精品福利短视频| 5528327男人天堂| 国产一区二区欧美三区| 亚洲国产精品久久久久蜜桃| 国产免费av一区二区凹凸四季| 51国产偷自视频在线播放| 97黄网站在线观看| 欧美爆乳肉感大码在线观看| 亚洲av自拍偷拍综合| 久久久久五月天丁香社区| 午夜国产免费福利av| 国产真实乱子伦a视频 | 国产一区二区三免费视频| 天天射夜夜操狠狠干| 日韩精品二区一区久久| 成人性爱在线看四区| 超碰97人人澡人人| 无码日韩人妻精品久久| 亚洲码av无色中文| 91福利在线视频免费观看| 视频二区在线视频观看| 3337p日本欧洲大胆色噜噜| 91国内视频在线观看| 亚洲2021av天堂| 黄色视频在线观看高清无码| 北条麻妃肉色丝袜视频| 午夜影院在线观看视频羞羞羞| 国产黄色高清资源在线免费观看| 亚洲特黄aaaa片| 日韩无码国产精品强奸乱伦| 沙月文乃人妻侵犯中文字幕在线| 中文字幕人妻三级在线观看| 伊拉克及约旦宣布关闭领空| 天干天天天色天天日天天射| 中文字幕 亚洲av| 一区二区三区的久久的蜜桃的视频 | 欧美麻豆av在线播放| 中文字幕一区二区人妻电影冢本| 亚洲丝袜老师诱惑在线观看| 91亚洲手机在线视频播放| 大鸡巴插入美女黑黑的阴毛| 91精品激情五月婷婷在线| 亚洲av日韩精品久久久| asmr福利视频在线观看| 蜜桃视频在线欧美一区| 国产极品精品免费视频| 日本韩国免费一区二区三区视频| 国产精品福利小视频a| 国产在线免费观看成人| 中文字幕 亚洲av| 国产内射中出在线观看| 亚洲激情av一区二区| 不卡日韩av在线观看| 久草福利电影在线观看| 日日夜夜大香蕉伊人| 亚洲推理片免费看网站| 日本韩国亚洲综合日韩欧美国产| 午夜福利资源综合激情午夜福利资| 亚洲精品无码久久久久不卡| 99精品免费久久久久久久久a| 国产精品熟女久久久久浪潮| 日本女大学生的黄色小视频| 红桃av成人在线观看| 日本成人不卡一区二区| 大香蕉伊人国产在线| 最新欧美一二三视频| 不卡一不卡二不卡三| 国产精品三级三级三级| 小泽玛利亚视频在线观看| 免费看国产av网站| 国内资源最丰富的网站| 高清成人av一区三区| 天天日天天做天天日天天做| 国产在线一区二区三区麻酥酥| 国产综合高清在线观看| av高潮迭起在线观看| 99国内小视频在现欢看| 亚洲成人情色电影在线观看| 在线免费观看日本伦理| 青娱乐极品视频青青草| 日本熟女50视频免费| 欧美成一区二区三区四区| 欧美日韩在线精品一区二区三| 视频一区 视频二区 视频| 亚洲精品无码久久久久不卡 | 久久尻中国美女视频| 欧美国品一二三产区区别| 一级黄片久久久久久久久| 日韩av熟妇在线观看| 亚洲丝袜老师诱惑在线观看| 欧美在线一二三视频| 18禁精品网站久久| 午夜影院在线观看视频羞羞羞| 久久精品亚洲成在人线a| 亚洲精品 日韩电影| av中文字幕福利网| 狠狠鲁狠狠操天天晚上干干| 91久久国产成人免费网站| 涩爱综合久久五月蜜臀| 亚洲国产在人线放午夜| 亚洲av天堂在线播放| 日韩北条麻妃一区在线| 亚洲激情偷拍一区二区| 久久久久久久久久久久久97| 可以在线观看的av中文字幕| 99一区二区在线观看| 337p日本大胆欧美人| 亚洲午夜电影之麻豆| 午夜精彩视频免费一区| 久久机热/这里只有| 综合色区亚洲熟妇shxstz| 国产精品成人xxxx| 337p日本大胆欧美人| 成人av免费不卡在线观看| 亚洲国产第一页在线观看| 一区二区视频在线观看免费观看| 丁香花免费在线观看中文字幕| 亚洲va欧美va人人爽3p| aaa久久久久久久久| 2020久久躁狠狠躁夜夜躁| 18禁精品网站久久| 在线制服丝袜中文字幕| 欧美在线一二三视频| 国产av一区2区3区| 青青草原网站在线观看| 午夜激情高清在线观看| 国产精品大陆在线2019不卡| 亚洲国产欧美国产综合在线| 人人超碰国字幕观看97| 91国产资源在线视频| 99精品视频在线观看免费播放| 亚洲精品中文字幕下载| 国产麻豆国语对白露脸剧情| 日本美女成人在线视频| 亚洲一区二区三区在线高清| 93精品视频在线观看| 国产视频网站一区二区三区| 天天色天天操天天透| 一区二区视频视频视频| 999九九久久久精品| 又色又爽又黄的美女裸体| 欧美少妇性一区二区三区| 成人区人妻精品一区二视频| 在线观看欧美黄片一区二区三区 | 白白操白白色在线免费视频 | 国产精品视频资源在线播放| 色吉吉影音天天干天天操| 在线观看的a站 最新| 小泽玛利亚视频在线观看| 宅男噜噜噜666国产| 日本少妇人妻xxxxxhd| 黑人性生活视频免费看| 国产午夜福利av导航| 91国内视频在线观看| 极品粉嫩小泬白浆20p主播| 日本少妇人妻xxxxx18| 99久久99一区二区三区| av森泽佳奈在线观看| 免费一级黄色av网站| 日韩中文字幕在线播放第二页 | 天天摸天天日天天操| 在线免费观看国产精品黄色| 五十路av熟女松本翔子| 青青尤物在线观看视频网站| 岳太深了紧紧的中文字幕| 国产黄色a级三级三级三级| 午夜av一区二区三区| 2018在线福利视频| 日韩人妻丝袜中文字幕| 亚洲国产第一页在线观看| 熟女视频一区,二区,三区| 国产中文字幕四区在线观看| 美女 午夜 在线视频| 天天操天天插天天色| 一色桃子久久精品亚洲 | 女生自摸在线观看一区二区三区 | 国内资源最丰富的网站| 亚洲人妻av毛片在线| 欧美国品一二三产区区别| 在线免费观看99视频| 91精品国产91久久自产久强| 成人亚洲精品国产精品| 第一福利视频在线观看| 欧美男人大鸡吧插女人视频| www天堂在线久久| 家庭女教师中文字幕在线播放| 青青青国产片免费观看视频| 久久久91蜜桃精品ad| 老师啊太大了啊啊啊尻视频| 在线 中文字幕 一区| 男生用鸡操女生视频动漫| 天天干天天插天天谢| 天堂av在线官网中文| 美女av色播在线播放| 日本一区二区三区免费小视频| 青青伊人一精品视频| 老司机免费视频网站在线看| 99久久中文字幕一本人| 天天操天天插天天色| 国产黄色高清资源在线免费观看| 孕妇奶水仑乱A级毛片免费看| 三级等保密码要求条款| 99热这里只有精品中文| 中文字幕在线欧美精品| 国产白嫩美女一区二区| 精彩视频99免费在线| 2020久久躁狠狠躁夜夜躁| 成人影片高清在线观看 | 色秀欧美视频第一页| 日本性感美女三级视频| 午夜在线精品偷拍一区二| 一级黄片久久久久久久久| 天天干狠狠干天天操| 精品欧美一区二区vr在线观看| 经典av尤物一区二区| 大屁股肉感人妻中文字幕在线| 国内资源最丰富的网站| 婷婷久久一区二区字幕网址你懂得| 国产日韩一区二区在线看| 国产日本精品久久久久久久| 欧美在线一二三视频| 18禁精品网站久久| 亚洲人妻国产精品综合| 欧美激情精品在线观看| 欧美黑人巨大性xxxxx猛交| 成人24小时免费视频| 国产黄色a级三级三级三级| 97香蕉碰碰人妻国产樱花| aⅴ五十路av熟女中出| 天堂资源网av中文字幕| 97超碰国语国产97超碰| 2020韩国午夜女主播在线| 91麻豆精品91久久久久同性| 亚洲欧美一卡二卡三卡| 日韩欧美一级黄片亚洲| 成人sm视频在线观看| 日韩美av高清在线| 老司机深夜免费福利视频在线观看| 淫秽激情视频免费观看| 中文字幕在线永久免费播放| 东京热男人的av天堂| 中文亚洲欧美日韩无线码| 亚洲熟妇x久久av久久| 99精品亚洲av无码国产另类| 国产精品国产三级国产精东| 九色精品视频在线播放| 欧美日韩熟女一区二区三区| 免费费一级特黄真人片 | 国产乱弄免费视频观看| 国产中文精品在线观看| 亚洲免费av在线视频| 久久h视频在线观看| 一级黄色av在线观看| 精品一区二区三区欧美| 中文乱理伦片在线观看| 超pen在线观看视频公开97| 91国偷自产一区二区三区精品| 11久久久久久久久久久| 日韩激情文学在线视频| 亚洲欧美自拍另类图片| 最新激情中文字幕视频| 乱亲女秽乱长久久久| 人妻少妇性色欲欧美日韩| 午夜国产福利在线观看| 精品欧美一区二区vr在线观看| 亚洲人妻国产精品综合| 日本午夜福利免费视频| 精品国产在线手机在线| 91久久综合男人天堂| 91九色国产熟女一区二区| 红桃av成人在线观看| 中文字幕av第1页中文字幕| 亚洲激情av一区二区| 一区二区三区四区中文| 熟女人妻在线中出观看完整版| 99精品亚洲av无码国产另类| 人妻少妇一区二区三区蜜桃| 丝袜肉丝一区二区三区四区在线| 国产真实乱子伦a视频| 91www一区二区三区| 夜夜骑夜夜操夜夜奸| 亚洲国产美女一区二区三区软件 | 欧美一区二区中文字幕电影| 黄色黄色黄片78在线| 深夜男人福利在线观看| 亚洲欧美一卡二卡三卡| 日本黄色特一级视频| 国产午夜无码福利在线看| 国产精品成人xxxx| 特级欧美插插插插插bbbbb| 少妇深喉口爆吞精韩国| 91精品国产91久久自产久强| 欧美熟妇一区二区三区仙踪林| 午夜精品一区二区三区城中村| 国产av自拍偷拍盛宴| 午夜久久久久久久99| 久久久噜噜噜久久熟女av| 欧美日韩人妻久久精品高清国产 | 天天日天天摸天天爱| 久草电影免费在线观看| 亚洲图片欧美校园春色| 天天射,天天操,天天说| 色97视频在线播放| 亚洲中文精品人人免费| brazzers欧熟精品系列| 国产日韩精品电影7777| 亚洲国产欧美一区二区丝袜黑人| 青青草精品在线视频观看| 97人妻人人澡爽人人精品| 久草视频首页在线观看| 国产麻豆剧果冻传媒app| 欧美一级片免费在线成人观看| 999九九久久久精品| 亚洲1区2区3区精华液| 人人人妻人人澡人人| 国产一级麻豆精品免费| 国产亚洲视频在线二区| 欧美一区二区三区激情啪啪啪| 黑人3p华裔熟女普通话| 超黄超污网站在线观看| 日韩欧美国产一区不卡| 懂色av之国产精品| 亚洲av男人天堂久久| 久久国产精品精品美女| 天天摸天天亲天天舔天天操天天爽 | 97精品人妻一区二区三区精品| 亚洲的电影一区二区三区| 国产亚洲视频在线观看| 激情国产小视频在线| 淫秽激情视频免费观看| 人妻少妇中文有码精品| 欧洲精品第一页欧洲精品亚洲 | 人妻丰满熟妇综合网| 国产精品国产三级国产午| 夜女神免费福利视频| 玖玖一区二区在线观看| 日韩欧美国产精品91| 国产高清在线观看1区2区| 毛片av在线免费看| av在线免费中文字幕| av在线播放国产不卡| 欧美日韩高清午夜蜜桃大香蕉| 亚洲免费福利一区二区三区| 亚洲中文字幕人妻一区| 免费大片在线观看视频网站| 青青青青青手机视频| 2020国产在线不卡视频| 东京热男人的av天堂| 二区中出在线观看老师| 成年女人免费播放视频| 一区二区三区四区五区性感视频| 久久精品国产999| 国产精品久久久久久美女校花| 青草亚洲视频在线观看| 青青草在观免费国产精品| 美洲精品一二三产区区别| 日韩伦理短片在线观看| 一色桃子久久精品亚洲| 午夜国产福利在线观看| 成人H精品动漫在线无码播放| 欧美色婷婷综合在线| 久久久久久cao我的性感人妻 | 男人的天堂一区二区在线观看| 国产精品黄片免费在线观看| 青青草原网站在线观看| 青青草人人妻人人妻| 欧美日韩情色在线观看| 国产无遮挡裸体免费直播视频| heyzo蜜桃熟女人妻| 大鸡吧插入女阴道黄色片| 人妻3p真实偷拍一二区| 国产欧美精品一区二区高清| 天天操天天污天天射| 日韩人妻xxxxx| 动漫黑丝美女的鸡巴| 天天干天天操天天扣| 可以免费看的www视频你懂的| 日韩国产乱码中文字幕| 爆乳骚货内射骚货内射在线 | 亚洲高清自偷揄拍自拍| 极品性荡少妇一区二区色欲| 蜜桃视频入口久久久| 水蜜桃一区二区三区在线观看视频| 日本人竟这样玩学生妹| 国产精品一区二区三区蜜臀av| 亚洲国产香蕉视频在线播放| 91麻豆精品91久久久久同性| 2017亚洲男人天堂| 亚洲一区二区三区久久午夜| 日韩国产乱码中文字幕| 内射久久久久综合网| 在线观看免费岛国av| 91麻豆精品传媒国产黄色片| 亚洲精品午夜久久久久| 国产精品亚洲а∨天堂免| 精品人妻一二三区久久| 和邻居少妇愉情中文字幕| 夜夜嗨av一区二区三区中文字幕| 在线免费观看日本片| 午夜在线观看一区视频| 日韩欧美中文国产在线| 福利视频网久久91| 国产高清女主播在线| 阿v天堂2014 一区亚洲| 精品一线二线三线日本| 在线亚洲天堂色播av电影| 亚洲精品一线二线在线观看| 91精品国产91青青碰| 玩弄人妻熟妇性色av少妇| 啊用力插好舒服视频| 巨乳人妻日下部加奈被邻居中出| 日本黄色特一级视频| 国产视频一区二区午夜| 男大肉棒猛烈插女免费视频| 懂色av之国产精品| 亚洲成人激情av在线| 777奇米久久精品一区| 中文字幕人妻被公上司喝醉在线| 婷婷久久久久深爱网| 精品一区二区三区三区色爱| 少妇被强干到高潮视频在线观看| 国内资源最丰富的网站| 亚洲日本一区二区久久久精品| 99久久成人日韩欧美精品| 亚洲图片欧美校园春色| 青青青青视频在线播放| 66久久久久久久久久久| 91综合久久亚洲综合| 日韩少妇人妻精品无码专区| 3D动漫精品啪啪一区二区下载| 日韩欧美亚洲熟女人妻| 亚洲免费在线视频网站| 久久久久久cao我的性感人妻| 91久久综合男人天堂| 成人久久精品一区二区三区| 国产黄网站在线观看播放| 久久丁香婷婷六月天| 国产污污污污网站在线| 欧美性受xx黑人性猛交| 欧美一级色视频美日韩| 肏插流水妹子在线乐播下载| 中文字幕人妻一区二区视频| 在线观看视频一区麻豆| 超级av免费观看一区二区三区| 狍和女人的王色毛片| 亚洲欧美激情中文字幕| 日本熟女50视频免费| av破解版在线观看| 精品久久久久久久久久久久人妻| 人妻av无码专区久久绿巨人| 91精品资源免费观看| 青青青青青免费视频| 91超碰青青中文字幕| 福利午夜视频在线观看| huangse网站在线观看| 国产福利小视频免费观看| 欧美一区二区三区啪啪同性| a v欧美一区=区三区| 午夜美女福利小视频| 中文字幕中文字幕 亚洲国产| 久草视频 久草视频2| 欧美精品欧美极品欧美视频| 中文字幕第一页国产在线| 青青草亚洲国产精品视频| 97少妇精品在线观看| 亚洲av在线观看尤物| 日本少妇精品免费视频| 自拍 日韩 欧美激情| 中文字幕乱码av资源| 女同久久精品秋霞网| 久久久久久久一区二区三| 黑人解禁人妻叶爱071| 精彩视频99免费在线| 视频在线免费观看你懂得| 99精品国产aⅴ在线观看| 青青伊人一精品视频| 国产麻豆国语对白露脸剧情| 免费在线播放a级片| 人人妻人人爽人人添夜| 熟女在线视频一区二区三区| 日本韩国免费福利精品| 懂色av之国产精品| 日本裸体熟妇区二区欧美| 日韩一区二区电国产精品| 亚洲成人国产综合一区| 在线免费观看国产精品黄色| free性日本少妇| 黄色黄色黄片78在线| 五月天久久激情视频| 中英文字幕av一区| 农村胖女人操逼视频| 日曰摸日日碰夜夜爽歪歪| 91大屁股国产一区二区| 亚洲2021av天堂| 高清一区二区欧美系列| 国产第一美女一区二区三区四区| 国产清纯美女al在线| 免费在线看的黄网站| 中文字幕免费福利视频6| 在线观看免费视频网| 91九色porny国产在线| 性生活第二下硬不起来| 中文乱理伦片在线观看| 亚洲欧美综合另类13p| 中文字幕免费福利视频6| 熟女少妇激情五十路| 硬鸡巴动态操女人逼视频| av大全在线播放免费| 78色精品一区二区三区| 欧美一级片免费在线成人观看| 唐人色亚洲av嫩草| 久草福利电影在线观看| 日韩一区二区电国产精品| 黑人进入丰满少妇视频| 一区二区麻豆传媒黄片| 在线亚洲天堂色播av电影| 亚洲熟女综合色一区二区三区四区| 91高清成人在线视频| 又粗又硬又猛又爽又黄的| 久久这里只有精彩视频免费| 免费看国产又粗又猛又爽又黄视频 | 亚洲最大黄 嗯色 操 啊| 国产精品日韩欧美一区二区| 午夜极品美女福利视频| 精品国产在线手机在线| 99精品久久久久久久91蜜桃| 天天躁夜夜躁日日躁a麻豆| 9国产精品久久久久老师| 欧美一区二区三区在线资源| 天天日天天日天天射天天干| 人妻丝袜精品中文字幕| 午夜青青草原网在线观看| 最新国产亚洲精品中文在线| 啪啪啪啪啪啪啪免费视频| 美女日逼视频免费观看| 中文字幕无码日韩专区免费| 99人妻视频免费在线| 亚洲精品 日韩电影| 人妻av无码专区久久绿巨人| 婷婷六月天中文字幕| 亚洲男人在线天堂网| 首之国产AV医生和护士小芳| www日韩a级s片av| 国产精品自拍视频大全| 91国内视频在线观看| 女同性ⅹxx女同h偷拍| 一区二区三区四区五区性感视频| 人妻丰满熟妇综合网| 在线观看av亚洲情色| 日韩精品二区一区久久| 蜜臀成人av在线播放| 欧美一级片免费在线成人观看| 国产在线自在拍91国语自产精品| 大骚逼91抽插出水视频| 欧美va不卡视频在线观看| 深田咏美亚洲一区二区| 国产激情av网站在线观看| 国产精品手机在线看片| 91免费黄片可看视频| 日韩成人性色生活片| 欧美精品资源在线观看| 欧美亚洲中文字幕一区二区三区 | 日韩美女综合中文字幕pp| 2020久久躁狠狠躁夜夜躁| 国产不卡av在线免费| 欲乱人妻少妇在线视频裸| 国产麻豆剧果冻传媒app| 日韩a级黄色小视频| 一区二区久久成人网| 亚洲精品国偷自产在线观看蜜桃| 日日夜夜狠狠干视频| 蜜桃视频在线欧美一区| 护士特殊服务久久久久久久| 成年人黄视频在线观看| 色97视频在线播放| 亚洲综合一区成人在线| 一区二区三区毛片国产一区| 国产a级毛久久久久精品| 人人妻人人爽人人澡人人精品| 在线观看视频污一区| 东游记中文字幕版哪里可以看到| 国产又粗又黄又硬又爽| 75国产综合在线视频| 亚洲va国产va欧美va在线| 国产chinesehd精品麻豆| 午夜国产免费福利av| 中文字幕一区二 区二三区四区| 白白操白白色在线免费视频| japanese五十路熟女熟妇| 任你操视频免费在线观看| 亚洲另类图片蜜臀av| 端庄人妻堕落挣扎沉沦| 青青热久免费精品视频在线观看| 骚货自慰被发现爆操| 国产janese在线播放| 女生被男生插的视频网站| 国产亚洲成人免费在线观看| 黄片大全在线观看观看| 青青草国内在线视频精选| 一区二区三区日韩久久| 欧美区一区二区三视频| 99精品国产自在现线观看| 成年人该看的视频黄免费| 日韩欧美高清免费在线| 青青尤物在线观看视频网站| 高清成人av一区三区| 伊人日日日草夜夜草| 欧美激情精品在线观看| 夜色撩人久久7777| 亚洲精品一线二线在线观看| 欧洲欧美日韩国产在线| 在线观看av2025| 91she九色精品国产| av网址国产在线观看| 一级黄片久久久久久久久| 91中文字幕免费在线观看| 黑人大几巴狂插日本少妇| 欧美久久一区二区伊人| 国产综合高清在线观看| 国产精品系列在线观看一区二区| 国产av自拍偷拍盛宴| 香港三日本三韩国三欧美三级| av男人天堂狠狠干| 91自产国产精品视频| 91精品国产综合久久久蜜 | 又色又爽又黄的美女裸体| 天天干狠狠干天天操| 99精品亚洲av无码国产另类| 黑人巨大的吊bdsm| 亚洲图片欧美校园春色| 男女啪啪视频免费在线观看| 中文字幕之无码色多多| 亚洲护士一区二区三区| 亚洲成人情色电影在线观看| 偷拍美女一区二区三区| 黄色av网站免费在线| 91大神福利视频网| 亚洲午夜高清在线观看| av手机免费在线观看高潮| 香蕉91一区二区三区| 2021最新热播中文字幕| 神马午夜在线观看视频| 97欧洲一区二区精品免费| 中文字幕人妻一区二区视频| 3344免费偷拍视频| 激情五月婷婷综合色啪| 亚洲精品无码久久久久不卡| 亚洲成人激情av在线| 亚洲日产av一区二区在线| 天天做天天干天天操天天射| 一区二区三区av高清免费| 日韩人妻在线视频免费| 日韩一个色综合导航| 亚洲一区二区三区精品乱码| 亚洲熟妇x久久av久久| 中文字幕高清免费在线人妻 | 2021久久免费视频| 久久久久久久99精品| 欧美日本在线观看一区二区| 亚洲自拍偷拍综合色| 欧美 亚洲 另类综合| 亚洲高清自偷揄拍自拍| 亚洲精品乱码久久久本| 大骚逼91抽插出水视频| 午夜免费观看精品视频| 大肉大捧一进一出好爽在线视频| 国产成人无码精品久久久电影| 成人性爱在线看四区| 在线国产精品一区二区三区| av森泽佳奈在线观看| 91国产在线视频免费观看| 国产福利在线视频一区| 美女福利写真在线观看视频| 97年大学生大白天操逼| 男女之间激情网午夜在线| 黄片色呦呦视频免费看| 2o22av在线视频| 不卡精品视频在线观看| 日韩精品中文字幕在线| 天堂女人av一区二区| 久久精品视频一区二区三区四区| 国产片免费观看在线观看| 日韩人妻丝袜中文字幕| 美女大bxxxx内射| 亚洲av无女神免非久久| 把腿张开让我插进去视频| 精品91自产拍在线观看一区| 久久美欧人妻少妇一区二区三区 | 蜜臀成人av在线播放| 午夜美女少妇福利视频| 日本在线不卡免费视频| 欧美精品黑人性xxxx| 人妻久久久精品69系列| 欧美黄片精彩在线免费观看| 大骚逼91抽插出水视频| 年轻的人妻被夫上司侵犯| 午夜大尺度无码福利视频| 亚洲中文字字幕乱码| 国产一区二区久久久裸臀| 91在线免费观看成人| 大香蕉大香蕉大香蕉大香蕉大香蕉| 91福利在线视频免费观看| 亚洲熟妇久久无码精品| av久久精品北条麻妃av观看| 青青青青青操视频在线观看| 亚洲日本一区二区三区| 视频一区 视频二区 视频| 熟妇一区二区三区高清版| 精品高跟鞋丝袜一区二区| 久久久久久99国产精品| 久久三久久三久久三久久| 亚洲国产欧美一区二区丝袜黑人| 欧美日韩v中文在线| 久久久久久97三级| 午夜场射精嗯嗯啊啊视频| 日韩在线中文字幕色| 在线免费观看99视频| 中文字幕在线观看极品视频| 熟妇一区二区三区高清版| 亚洲国产欧美国产综合在线| 国产成人精品av网站| 成人性黑人一级av| 欧美va亚洲va天堂va| 午夜在线观看岛国av,com| 亚洲欧美一卡二卡三卡| 中字幕人妻熟女人妻a62v网| 天天射夜夜操狠狠干| 偷拍3456eee| 天天射,天天操,天天说| 亚洲午夜高清在线观看| 欧美女同性恋免费a| 日本av高清免费网站| 38av一区二区三区| 11久久久久久久久久久| 日比视频老公慢点好舒服啊| 中文字幕亚洲中文字幕| 91精品国产高清自在线看香蕉网| 91老师蜜桃臀大屁股| 都市家庭人妻激情自拍视频| 精品91自产拍在线观看一区| 国产三级影院在线观看| 一区二区三区四区五区性感视频| 亚洲综合色在线免费观看| 精品久久婷婷免费视频| 成人24小时免费视频| 激情啪啪啪啪一区二区三区| 激情国产小视频在线| 日本裸体熟妇区二区欧美| 好吊视频—区二区三区| 日本午夜爽爽爽爽爽视频在线观看 | 午夜激情高清在线观看| 国产V亚洲V天堂无码欠欠| 免费成人av中文字幕| 自拍偷拍亚洲欧美在线视频| 啊啊好大好爽啊啊操我啊啊视频| 99热这里只有精品中文| 色婷婷综合激情五月免费观看| 精品美女福利在线观看| 欧美天堂av无线av欧美| 丁香花免费在线观看中文字幕| 水蜜桃一区二区三区在线观看视频| 国产一区二区三免费视频| 午夜精品一区二区三区城中村| 亚洲人妻30pwc| 亚洲精品成人网久久久久久小说| 99re国产在线精品| 欧美一区二区三区久久久aaa| 2021天天色天天干| 性欧美日本大妈母与子| 又大又湿又爽又紧A视频| 精品乱子伦一区二区三区免费播| 一二三中文乱码亚洲乱码one| 五十路在线观看完整版| 特大黑人巨大xxxx| mm131美女午夜爽爽爽| 久久这里只有精品热视频| 操日韩美女视频在线免费看| 国产伊人免费在线播放| 在线视频国产欧美日韩| 欧美专区第八页一区在线播放 | 播放日本一区二区三区电影| 久久午夜夜伦痒痒想咳嗽P| 93精品视频在线观看| 日本一道二三区视频久久| 国产黄色大片在线免费播放| 99re国产在线精品| 福利视频网久久91| 看一级特黄a大片日本片黑人| chinese国产盗摄一区二区| 亚洲一区二区三区在线高清| 日韩精品电影亚洲一区| 亚洲自拍偷拍综合色| 国产精彩对白一区二区三区 | 久久精品美女免费视频| 人妻少妇亚洲一区二区| 日本少妇人妻xxxxxhd| 国产黄色高清资源在线免费观看| av资源中文字幕在线观看| 亚洲午夜在线视频福利| 超pen在线观看视频公开97| 精品suv一区二区69| 一区二区三区四区视频| 欧美日韩不卡一区不区二区| 久久久久91精品推荐99| 国产av自拍偷拍盛宴| 日韩国产乱码中文字幕| 国产精品自拍视频大全| 国产综合高清在线观看| 亚洲粉嫩av一区二区三区| 2020久久躁狠狠躁夜夜躁 | 免费高清自慰一区二区三区网站 | 亚洲天堂av最新网址| 亚洲中文字幕综合小综合| 天天干天天啪天天舔| 成年人该看的视频黄免费| 亚洲精品国品乱码久久久久| 九九热99视频在线观看97| 亚洲国产免费av一区二区三区| 一区二区三区精品日本| 国产精品视频资源在线播放| 一级黄片久久久久久久久| 亚洲一区二区人妻av| 日韩午夜福利精品试看| 加勒比视频在线免费观看| 日本熟妇一区二区x x| 成人乱码一区二区三区av| 亚洲麻豆一区二区三区| 老熟妇凹凸淫老妇女av在线观看| 国产一区av澳门在线观看| 国产美女午夜福利久久| 午夜场射精嗯嗯啊啊视频| 一区二区三区精品日本| 视频一区二区综合精品| 午夜精品一区二区三区4| 亚洲国产精品黑丝美女| 色秀欧美视频第一页| 爱有来生高清在线中文字幕| 98精产国品一二三产区区别| 亚洲欧美色一区二区| 人妻少妇亚洲精品中文字幕| 亚洲欧美久久久久久久久| 精品久久久久久高潮| 一本久久精品一区二区| 日本中文字幕一二区视频| 亚洲国产在人线放午夜| 日本黄在免费看视频| 很黄很污很色的午夜网站在线观看 | 激情人妻校园春色亚洲欧美| 成人精品在线观看视频| 福利一二三在线视频观看| 国产高清在线在线视频| 久久丁香婷婷六月天| 男人和女人激情视频| 精产国品久久一二三产区区别| 男人的网址你懂的亚洲欧洲av| 在线制服丝袜中文字幕| 亚洲一级 片内射视正片| 日韩一区二区电国产精品| 国产亚洲四十路五十路| 美女在线观看日本亚洲一区| 人妻久久久精品69系列| 国产精品入口麻豆啊啊啊| 中文字母永久播放1区2区3区| 国产午夜激情福利小视频在线| 老司机免费视频网站在线看| 老司机99精品视频在线观看| 激情五月婷婷免费视频| 国产高潮无码喷水AV片在线观看| 大白屁股精品视频国产| 大学生A级毛片免费视频| 亚洲一级av无码一级久久精品| 久久热这里这里只有精品| 午夜dv内射一区区| 丰满的继坶3中文在线观看| 国产精品自拍偷拍a| 亚洲午夜高清在线观看| av中文字幕福利网| 天堂av中文在线最新版| 偷拍3456eee| 又色又爽又黄的美女裸体| 成人精品在线观看视频| 亚洲在线一区二区欧美| 国内资源最丰富的网站| 2020中文字幕在线播放| 国产精品大陆在线2019不卡| 人妻久久久精品69系列| 日韩精品激情在线观看| 亚洲精品在线资源站| 韩国AV无码不卡在线播放| 福利一二三在线视频观看| 少妇露脸深喉口爆吞精| 一级黄片久久久久久久久| 久久久久久久99精品| 五月天久久激情视频| 天码人妻一区二区三区在线看| 大香蕉日本伊人中文在线| 黄色无码鸡吧操逼视频| 欧美第一页在线免费观看视频| 国产剧情演绎系列丝袜高跟| 青青草原网站在线观看| 天天综合天天综合天天网| 18禁污污污app下载| 人妻丰满熟妇综合网| 亚洲蜜臀av一区二区三区九色| 老鸭窝在线观看一区| 成人av中文字幕一区| 蜜桃视频17c在线一区二区| 亚洲另类在线免费观看| 免费看国产又粗又猛又爽又黄视频| 粉嫩小穴流水视频在线观看| 日本午夜爽爽爽爽爽视频在线观看 | 欧美另类一区二区视频| 青青伊人一精品视频| 亚洲精品ww久久久久久| 亚洲码av无色中文| 无码精品一区二区三区人 | 亚洲va国产va欧美va在线| 中国黄片视频一区91| 精品suv一区二区69| 国产又粗又黄又硬又爽| 福利片区一区二体验区| 欧美精品亚洲精品日韩在线| 人妻少妇精品久久久久久 | 中文字幕高清资源站| 韩国爱爱视频中文字幕| 制服丝袜在线人妻中文字幕| 成人精品在线观看视频| 亚洲欧美激情中文字幕| 99国内精品永久免费视频| 91传媒一区二区三区| 中文字幕一区二区亚洲一区| 国产精品三级三级三级| 日本一二三区不卡无| 成人sm视频在线观看| 大胆亚洲av日韩av| 欧美激情精品在线观看| 国产精品手机在线看片| 97国产在线观看高清| 日本熟女50视频免费| 亚洲欧美精品综合图片小说| av日韩在线免费播放| 精品美女福利在线观看| 亚洲中文字幕校园春色| 热99re69精品8在线播放| 高清成人av一区三区| 大鸡巴后入爆操大屁股美女| 亚洲免费福利一区二区三区| 亚洲图库另类图片区| 日本熟妇色熟妇在线观看| 伊人成人综合开心网| 91成人在线观看免费视频| 中文字幕一区二区自拍| 91国产在线免费播放| 日韩欧美在线观看不卡一区二区| 日本后入视频在线观看| 久久久久久久一区二区三| 精品久久久久久高潮| 久久久久久97三级| 果冻传媒av一区二区三区| 精品91自产拍在线观看一区| 久久热久久视频在线观看| 亚洲成人免费看电影| 免费无码人妻日韩精品一区二区| av一区二区三区人妻| 偷拍自拍国产在线视频| 99精品视频在线观看婷婷| 三级av中文字幕在线观看| 自拍偷拍亚洲另类色图| 一二三区在线观看视频| 91在线免费观看成人| 中文字幕午夜免费福利视频| 精品区一区二区三区四区人妻| 日日操夜夜撸天天干| 亚洲av自拍偷拍综合| 懂色av之国产精品| 粉嫩av蜜乳av蜜臀| 玖玖一区二区在线观看| 姐姐的朋友2在线观看中文字幕 | 91福利在线视频免费观看| 午夜毛片不卡免费观看视频| 99视频精品全部15| 亚洲精品午夜aaa久久| 精品首页在线观看视频| 国产污污污污网站在线| 亚洲av天堂在线播放| 亚洲中文精品人人免费| 国产极品美女久久久久久| 亚洲自拍偷拍精品网| av在线免费中文字幕| 好吊视频—区二区三区| 热久久只有这里有精品| 国产高清精品极品美女| 精品人妻伦一二三区久| 在线成人日韩av电影| 亚洲男人在线天堂网| 91精品激情五月婷婷在线| 91精品免费久久久久久| 久久这里有免费精品| 一区二区三区四区五区性感视频| 国产揄拍高清国内精品对白| 少妇被强干到高潮视频在线观看 | 欧美成一区二区三区四区| 国产在线91观看免费观看| 国产janese在线播放| 久草视频 久草视频2| sejizz在线视频| 色偷偷伊人大杳蕉综合网| 天天射夜夜操狠狠干| 色综合天天综合网国产成人| 亚洲日本一区二区三区| 国产欧美日韩第三页| 久草电影免费在线观看| 91免费观看国产免费| 2020久久躁狠狠躁夜夜躁| 国产精彩对白一区二区三区| 日本性感美女写真视频| 春色激情网欧美成人| 欧美一级片免费在线成人观看| 亚洲青青操骚货在线视频| 欧美一级片免费在线成人观看 | 亚洲精品无码久久久久不卡| 女同性ⅹxx女同h偷拍| 午夜在线观看一区视频| 任我爽精品视频在线播放| 免费在线福利小视频| 粉嫩欧美美人妻小视频| av天堂中文免费在线| 亚洲欧美国产综合777| 久久一区二区三区人妻欧美| xxx日本hd高清| 高清成人av一区三区| 日日日日日日日日夜夜夜夜夜夜| av手机在线观播放网站| 亚洲综合一区二区精品久久| 制丝袜业一区二区三区| 沈阳熟妇28厘米大战黑人| 亚洲欧美另类手机在线| 亚洲精品久久视频婷婷| 一区国内二区日韩三区欧美| 欧美一级色视频美日韩| 初美沙希中文字幕在线| 91中文字幕最新合集| 中文字幕 亚洲av| 一区二区三区四区视频| 涩爱综合久久五月蜜臀| 在线播放国产黄色av| 青青青国产片免费观看视频| 色婷婷综合激情五月免费观看| 成年美女黄网站18禁久久| 青青草国内在线视频精选| 欧美日本在线观看一区二区| 人妻最新视频在线免费观看| 一级A一级a爰片免费免会员| 中文字幕,亚洲人妻| nagger可以指黑人吗| 中文字幕中文字幕 亚洲国产| 99精品国产免费久久| av乱码一区二区三区| 19一区二区三区在线播放| 人妻3p真实偷拍一二区| 亚洲国产40页第21页| 中文字幕综合一区二区| 男人天堂最新地址av| 啪啪啪啪啪啪啪啪啪啪黄色| 绝顶痉挛大潮喷高潮无码| 亚洲精品无码久久久久不卡| 摧残蹂躏av一二三区| 免费观看成年人视频在线观看| 1区2区3区4区视频在线观看| 又色又爽又黄的美女裸体| 日本中文字幕一二区视频| 成人高清在线观看视频| 摧残蹂躏av一二三区| 精品成人午夜免费看| 午夜精品一区二区三区更新| 国产精品一区二区av国| 成人激情文学网人妻| 北条麻妃av在线免费观看| 扒开让我视频在线观看| 欧美麻豆av在线播放| 国产又粗又黄又硬又爽| 91福利在线视频免费观看| 日本a级视频老女人| chinese国产盗摄一区二区 | 国产日韩一区二区在线看| 精品美女福利在线观看| 天天日天天添天天爽| 一区二区视频在线观看免费观看| 91自产国产精品视频| 大胸性感美女羞爽操逼毛片| 国产成人精品久久二区91| 青草久久视频在线观看| av完全免费在线观看av| 久久www免费人成一看片| 亚洲中文精品字幕在线观看| 天天日天天日天天射天天干| 端庄人妻堕落挣扎沉沦| 99久久超碰人妻国产| 国产日本精品久久久久久久| 男人靠女人的逼视频| 亚洲激情,偷拍视频| 天天日天天做天天日天天做| 亚洲 欧美 自拍 偷拍 在线| 亚洲欧美成人综合在线观看| 欧洲欧美日韩国产在线| 久久久超爽一二三av| 亚洲福利精品视频在线免费观看| 91高清成人在线视频| 被大鸡吧操的好舒服视频免费| 任你操视频免费在线观看| 在线播放国产黄色av| 日本人竟这样玩学生妹| 天堂av在线播放免费| 啊啊啊想要被插进去视频| 亚洲特黄aaaa片| 国产V亚洲V天堂无码欠欠| 蜜臀av久久久久久久| 国产亚州色婷婷久久99精品| 91人妻精品一区二区在线看| 熟女国产一区亚洲中文字幕| 中文字幕在线视频一区二区三区 | 亚洲熟妇久久无码精品| 亚洲精品午夜aaa久久| 100%美女蜜桃视频| 视频一区 二区 三区 综合| 国产+亚洲+欧美+另类| 日韩av有码一区二区三区4 | 91极品新人『兔兔』精品新作| 成人精品视频99第一页| 成年午夜免费无码区| 亚洲成人免费看电影| 日本乱人一区二区三区| 亚洲少妇高潮免费观看| 狠狠躁狠狠爱网站视频| 国产午夜亚洲精品麻豆| 亚洲一区二区三区五区| 3337p日本欧洲大胆色噜噜| 久久麻豆亚洲精品av| 5528327男人天堂| 成人高潮aa毛片免费| 国产欧美日韩在线观看不卡| 国产女人叫床高潮大片视频| 成人伊人精品色xxxx视频| 亚洲精品国产综合久久久久久久久 | 91极品大一女神正在播放| 美女张开两腿让男人桶av| 天天日天天干天天舔天天射| 视频久久久久久久人妻| 国产又粗又硬又大视频| 中文字幕综合一区二区| 宅男噜噜噜666免费观看| 视频一区二区综合精品| 国产精品自偷自拍啪啪啪| 国产精品黄色的av| 亚洲国产欧美国产综合在线| 亚洲精品国偷自产在线观看蜜桃| 国产日韩一区二区在线看| 日本人妻欲求不满中文字幕| 国产+亚洲+欧美+另类| 91国语爽死我了不卡| 啪啪啪啪啪啪啪啪av| 日本熟妇丰满厨房55| 91超碰青青中文字幕| 亚洲国产精品黑丝美女| 精品首页在线观看视频| 成年人黄色片免费网站| 少妇深喉口爆吞精韩国| 成人色综合中文字幕| 狠狠躁狠狠爱网站视频| 日本高清成人一区二区三区| 只有精品亚洲视频在线观看| 肏插流水妹子在线乐播下载| 天天操夜夜骑日日摸| 亚洲精品午夜久久久久| 三上悠亚和黑人665番号| 夜色撩人久久7777| 顶级尤物粉嫩小尤物网站| 黄片色呦呦视频免费看| jiuse91九色视频| 91极品新人『兔兔』精品新作| 日本少妇在线视频大香蕉在线观看| 成年人的在线免费视频| 绝顶痉挛大潮喷高潮无码| 久久丁香花五月天色婷婷| 高潮喷水在线视频观看| 日韩精品中文字幕在线| 51国产偷自视频在线播放| 中文乱理伦片在线观看| 国产亚洲天堂天天一区| 在线观看视频 你懂的| 老司机福利精品免费视频一区二区| 天天干天天插天天谢| 可以免费看的www视频你懂的| 在线观看黄色成年人网站| 人妻av无码专区久久绿巨人| av手机在线免费观看日韩av| 一区二区三区美女毛片| 91色九色porny| 国产亚洲国产av网站在线| 日韩在线中文字幕色| 日本丰满熟妇BBXBBXHD| 国产精品黄色的av| 91福利在线视频免费观看| 亚洲成人国产综合一区| 黄色片黄色片wyaa| 午夜久久香蕉电影网| 亚洲熟妇无码一区二区三区| av中文字幕电影在线看| av中文字幕国产在线观看| 天天做天天干天天舔| 99热这里只有国产精品6| 日本阿v视频在线免费观看| 男生舔女生逼逼视频| 国产麻豆乱子伦午夜视频观看| 美女少妇亚洲精选av| 国产中文精品在线观看| 老熟妇xxxhd老熟女| huangse网站在线观看| 国产又粗又猛又爽又黄的视频美国| 免费黄页网站4188| 日本高清在线不卡一区二区| 亚洲国产精品久久久久久6| 热思思国产99re| 色综合久久久久久久久中文| 午夜毛片不卡免费观看视频| 97色视频在线观看| 国产V亚洲V天堂无码欠欠| aiss午夜免费视频| 538精品在线观看视频| 国产三级精品三级在线不卡| 天天日天天干天天要| 姐姐的朋友2在线观看中文字幕 | 中文字幕在线视频一区二区三区| 国产美女午夜福利久久| 色97视频在线播放| 国产va在线观看精品| 亚洲1卡2卡三卡4卡在线观看| 国产日韩精品电影7777| 精品区一区二区三区四区人妻| 欧美日本aⅴ免费视频| 黑人3p华裔熟女普通话| 婷婷综合蜜桃av在线| 午夜激情久久不卡一区二区| aⅴ五十路av熟女中出| 天天操天天干天天插| 大香蕉伊人国产在线| 日韩欧美一级精品在线观看| 亚洲欧美激情中文字幕| 天天日天天爽天天爽| 二区中出在线观看老师 | 黄网十四区丁香社区激情五月天| 天天日天天干天天要| 国产视频精品资源网站| 黄色三级网站免费下载| 97资源人妻免费在线视频| 日本后入视频在线观看| 国产极品精品免费视频| 国产日韩av一区二区在线| av无限看熟女人妻另类av| 51国产偷自视频在线播放| 超pen在线观看视频公开97| 欧美激情电影免费在线| 免费人成黄页网站在线观看国产 | 精品日产卡一卡二卡国色天香| 欧美天堂av无线av欧美| 91精品综合久久久久3d动漫| 天天操天天干天天日狠狠插 | 北条麻妃高跟丝袜啪啪| 成人亚洲国产综合精品| 肏插流水妹子在线乐播下载| 美女大bxxxx内射| 久久久久久久精品成人热| 99av国产精品欲麻豆| 99热99re在线播放| 天美传媒mv视频在线观看| 日本最新一二三区不卡在线| 国产又粗又黄又硬又爽| 午夜精品一区二区三区福利视频| av中文字幕网址在线| 在线免费观看国产精品黄色| 成人18禁网站在线播放| av森泽佳奈在线观看 | 偷拍美女一区二区三区| 大香蕉伊人国产在线| 日韩精品啪啪视频一道免费| 成年人中文字幕在线观看| 毛片av在线免费看| 一区二区三区的久久的蜜桃的视频| 青青青视频自偷自拍38碰| 97年大学生大白天操逼| 91精品国产麻豆国产| 日本后入视频在线观看| 精内国产乱码久久久久久| 亚洲视频在线视频看视频在线| www天堂在线久久| 色综合天天综合网国产成人| 啊慢点鸡巴太大了啊舒服视频| 欧美久久久久久三级网| 蜜桃久久久久久久人妻| 11久久久久久久久久久| 亚洲av成人免费网站| 午夜激情精品福利视频| 亚洲中文字幕综合小综合| 丝袜肉丝一区二区三区四区在线| 亚洲av男人天堂久久| 国产剧情演绎系列丝袜高跟| 日本真人性生活视频免费看| 中文字幕 人妻精品| 成人av天堂丝袜在线观看| 超级福利视频在线观看| 中文字幕乱码人妻电影| 在线观看av2025| 亚洲午夜伦理视频在线| 99一区二区在线观看| 日韩美女精品视频在线观看网站| 夜色17s精品人妻熟女| 亚洲精品福利网站图片| 80电影天堂网官网| 黄色无码鸡吧操逼视频| 宅男噜噜噜666免费观看| 亚洲一区制服丝袜美腿| 国产亚洲国产av网站在线| 天天色天天操天天透| 天天躁日日躁狠狠躁躁欧美av| 日本熟女精品一区二区三区| 亚洲福利天堂久久久久久| 男人的网址你懂的亚洲欧洲av| 一二三中文乱码亚洲乱码one| 欧美少妇性一区二区三区| 亚洲国产在人线放午夜| 精品区一区二区三区四区人妻 | 日韩美女精品视频在线观看网站| gay gay男男瑟瑟在线网站| 精品成人午夜免费看| 直接观看免费黄网站| 特大黑人巨大xxxx| 韩国爱爱视频中文字幕| 美女被肏内射视频网站| 日本在线不卡免费视频| 青青草成人福利电影| 人妻少妇av在线观看| 97超碰人人搞人人| 国产a级毛久久久久精品| 亚洲熟女久久久36d| 视频啪啪啪免费观看| 绝色少妇高潮3在线观看| 在线观看视频一区麻豆| 久草极品美女视频在线观看| 成年午夜免费无码区| 9久在线视频只有精品| 男人插女人视频网站| 欧美精品一二三视频| 久久www免费人成一看片| 人人妻人人澡人人爽人人dvl| 超碰在线观看免费在线观看| 国产日韩精品一二三区久久久| 欧洲欧美日韩国产在线| 中文字幕最新久久久| 国产普通话插插视频| 久久精品美女免费视频| 国产黄色a级三级三级三级| 蜜桃视频在线欧美一区| 亚洲图片欧美校园春色| 又粗又硬又猛又爽又黄的| 日本后入视频在线观看| 亚洲另类伦春色综合小| 国产又粗又硬又猛的毛片视频| 91色九色porny| 国产亚洲视频在线二区| 亚洲一级av无码一级久久精品| 中文字幕人妻一区二区视频| 97青青青手机在线视频 | 国产janese在线播放| 日本黄色三级高清视频| 2021久久免费视频| 2021年国产精品自拍| 亚洲中文字幕人妻一区| 国产精品精品精品999| 夏目彩春在线中文字幕| 精品首页在线观看视频| 偷拍3456eee| 成人乱码一区二区三区av| 成人性爱在线看四区| 国内精品在线播放第一页| 爱有来生高清在线中文字幕| 日本性感美女三级视频| 天天射,天天操,天天说| 久草免费人妻视频在线| 自拍 日韩 欧美激情| 亚洲综合色在线免费观看| 五十路熟女人妻一区二| caoporn蜜桃视频| 欧美男人大鸡吧插女人视频| 中文字幕日韩精品就在这里| 最新中文字幕免费视频| 亚国产成人精品久久久| 久久久久久97三级| 人妻少妇性色欲欧美日韩| 2022国产综合在线干| 2019av在线视频| 精品亚洲在线免费观看| 91she九色精品国产| 在线免费观看欧美小视频| 国产精品人妻一区二区三区网站| 亚洲精品福利网站图片| 国产乱子伦一二三区| 日韩人妻xxxxx| 男女之间激情网午夜在线| 超碰97免费人妻麻豆| 91免费放福利在线观看| tube69日本少妇| 丝袜长腿第一页在线| 夏目彩春在线中文字幕| 亚洲av极品精品在线观看| 99热久久极品热亚洲| aaa久久久久久久久| 绯色av蜜臀vs少妇| 成人av中文字幕一区| 天天干天天日天天谢综合156| 免费一级黄色av网站| 最新欧美一二三视频| 人妻久久久精品69系列| 高潮视频在线快速观看国家快速| 很黄很污很色的午夜网站在线观看| 亚洲av无乱一区二区三区性色| 亚洲欧美福利在线观看| 亚洲av日韩高清hd| 日本一本午夜在线播放| 夜夜躁狠狠躁日日躁麻豆内射 | 粉嫩av蜜乳av蜜臀| 日本成人一区二区不卡免费在线| 在线观看国产网站资源| 黄色资源视频网站日韩| 亚洲在线观看中文字幕av| 东京热男人的av天堂| 在线视频精品你懂的| 五月天久久激情视频| 亚洲成人精品女人久久久| 免费人成黄页网站在线观看国产| 狍和女人的王色毛片| 亚洲成人线上免费视频观看| aⅴ五十路av熟女中出| 欧美爆乳肉感大码在线观看| 亚洲 自拍 色综合图| 久久久极品久久蜜桃| japanese五十路熟女熟妇| 大尺度激情四射网站| 熟女少妇激情五十路| 亚洲成人免费看电影| 亚洲免费国产在线日韩| 国产一区二区三免费视频| 久久久久五月天丁香社区| 国产伦精品一区二区三区竹菊| 中文字幕日韩人妻在线三区| 免费福利av在线一区二区三区| 超级av免费观看一区二区三区| 在线观看的黄色免费网站| 鸡巴操逼一级黄色气| 91国内视频在线观看| 福利午夜视频在线观看| 在线观看免费av网址大全| 午夜精品久久久久久99热| 午夜毛片不卡在线看| 岛国青草视频在线观看| 成年人黄色片免费网站| 婷婷六月天中文字幕| 中文字幕欧美日韩射射一| 日韩av大胆在线观看| 国产福利小视频免费观看| 99国产精品窥熟女精品| 欧美熟妇一区二区三区仙踪林| 久久国产精品精品美女| 香蕉91一区二区三区| 99re国产在线精品| 国产一区二区久久久裸臀| 深夜男人福利在线观看| 红杏久久av人妻一区| 精品少妇一二三视频在线| 日本黄在免费看视频| 最近中文2019年在线看| 亚洲成人免费看电影| 天美传媒mv视频在线观看| 亚洲变态另类色图天堂网| 国产精品探花熟女在线观看| 色呦呦视频在线观看视频| 中文字日产幕乱六区蜜桃| 国产91精品拍在线观看| 精品首页在线观看视频| av线天堂在线观看| 成人av久久精品一区二区| 91国内精品久久久久精品一| 人妻丝袜榨强中文字幕| 日本性感美女视频网站| 黑人解禁人妻叶爱071| 特大黑人巨大xxxx| 中文字幕日韩91人妻在线| 亚洲精品高清自拍av| 亚洲男人的天堂a在线| 天堂av在线官网中文| 2020av天堂网在线观看| 中文字幕一区二区人妻电影冢本| 五月天中文字幕内射| 青青青青爽手机在线| 狠狠的往里顶撞h百合| 播放日本一区二区三区电影| 岛国免费大片在线观看| 青青青青青青草国产| 97超碰最新免费在线观看| 国产极品精品免费视频| 女生被男生插的视频网站| 国产真实乱子伦a视频| 成人精品视频99第一页| 国产麻豆国语对白露脸剧情| 日韩熟女av天堂系列| 黑人巨大的吊bdsm| 天天做天天干天天舔| 97超碰免费在线视频| 人妻丝袜av在线播放网址| 亚洲午夜高清在线观看| 午夜精品一区二区三区福利视频| 五十路老熟女码av| 精品久久久久久久久久中文蒉| 在线制服丝袜中文字幕| 国产1区,2区,3区| 果冻传媒av一区二区三区| 欧美精品黑人性xxxx| 一级黄片大鸡巴插入美女| 色偷偷伊人大杳蕉综合网| 加勒比视频在线免费观看| 农村胖女人操逼视频| 天堂va蜜桃一区入口| av线天堂在线观看| 亚洲第一黄色在线观看| 亚洲综合另类精品小说| 国产熟妇人妻ⅹxxxx麻豆| 亚洲综合另类欧美久久| 日本女大学生的黄色小视频| 日日爽天天干夜夜操| 偷拍自拍福利视频在线观看| 中文字幕一区二区三区人妻大片| 日本熟妇一区二区x x| 少妇人妻久久久久视频黄片| 午夜国产免费福利av| 久久久久国产成人精品亚洲午夜| 在线视频国产欧美日韩| 亚洲国产欧美一区二区三区久久| 欧美日韩不卡一区不区二区| 日本后入视频在线观看| 97国产精品97久久| 顶级尤物粉嫩小尤物网站| 成人国产激情自拍三区| 国产高清女主播在线| 又粗又硬又猛又黄免费30| 激情小视频国产在线| 天天干天天啪天天舔| 在线观看av2025| 人妻另类专区欧美制服| 日韩a级黄色小视频| 美女张开两腿让男人桶av| 亚洲天堂成人在线观看视频网站| 国产老熟女伦老熟妇ⅹ| 国产成人精品av网站| 国产自拍黄片在线观看| 亚洲精品乱码久久久久久密桃明| 中文字幕乱码人妻电影| 久久久超爽一二三av| 中文字幕第三十八页久久| 亚洲精品高清自拍av| 日视频免费在线观看| 亚洲人人妻一区二区三区| 成人久久精品一区二区三区| 爆乳骚货内射骚货内射在线| 国产一区av澳门在线观看| 啊啊好慢点插舔我逼啊啊啊视频| 99精品免费久久久久久久久a| 天天艹天天干天天操| 亚洲欧美国产麻豆综合| 亚洲码av无色中文| 欧美va亚洲va天堂va| 啪啪啪啪啪啪啪免费视频| av天堂资源最新版在线看| 五十路熟女人妻一区二| 亚洲一区制服丝袜美腿| 在线成人日韩av电影| 欧美爆乳肉感大码在线观看| 国产真实灌醉下药美女av福利| 亚洲高清国产拍青青草原| 亚洲高清一区二区三区视频在线 | 伊拉克及约旦宣布关闭领空| 影音先锋女人av噜噜色| 亚洲高清自偷揄拍自拍| 青青在线视频性感少妇和隔壁黑丝 | huangse网站在线观看| 五月精品丁香久久久久福利社| 午夜美女少妇福利视频| 天天日天天干天天搡| 久久热这里这里只有精品| 91 亚洲视频在线观看| 人妻少妇精品久久久久久| 亚洲区美熟妇久久久久| 快点插进来操我逼啊视频| 精品乱子伦一区二区三区免费播| 91色秘乱一区二区三区| 男人操女人逼逼视频网站| 国产精品日韩欧美一区二区| 日本一二三区不卡无| 精品亚洲中文字幕av| 天天干夜夜操啊啊啊| 日韩欧美在线观看不卡一区二区| 偷拍3456eee| 大胸性感美女羞爽操逼毛片| 3D动漫精品啪啪一区二区下载| 天天操天天插天天色| 久久久久久99国产精品| 青青社区2国产视频| 日本特级片中文字幕| 在线 中文字幕 一区| 中文字幕一区的人妻欧美日韩| 自拍偷拍亚洲欧美在线视频| 青青草在观免费国产精品| asmr福利视频在线观看| 蜜桃专区一区二区在线观看| 国产视频网站一区二区三区| 大鸡吧插逼逼视频免费看| 亚洲 清纯 国产com| 亚洲综合图片20p| 91精品国产黑色丝袜| 大胆亚洲av日韩av| 激情五月婷婷综合色啪| 中文字幕亚洲中文字幕| 成人av在线资源网站| 亚洲男人在线天堂网| 久久久久久久久久久久久97| 伊人综合aⅴ在线网| 亚洲最大免费在线观看| aⅴ精产国品一二三产品| 91麻豆精品久久久久| 国产女人露脸高潮对白视频| 黄网十四区丁香社区激情五月天| 可以免费看的www视频你懂的| 只有精品亚洲视频在线观看| 美洲精品一二三产区区别| 丰满少妇翘臀后进式| 亚洲黄色av网站免费播放| 亚洲免费成人a v| 久草视频在线看免费| 久久久久久九九99精品| 夜色福利视频在线观看| AV天堂一区二区免费试看| 亚洲精品中文字幕下载| 国产福利小视频大全| 国产在线自在拍91国语自产精品| 日本www中文字幕| 亚洲中文精品字幕在线观看| 亚洲美女自偷自拍11页| 亚洲一区二区久久久人妻| 精品国产午夜视频一区二区| h国产小视频福利在线观看| 2022国产综合在线干| 国产精品人妻熟女毛片av久| 姐姐的朋友2在线观看中文字幕| 国产又色又刺激在线视频| 亚洲一级av大片免费观看| 天天干夜夜操天天舔| 日韩欧美国产一区不卡| 婷婷色中文亚洲网68| mm131美女午夜爽爽爽| av在线免费观看亚洲天堂| 75国产综合在线视频| 亚洲av天堂在线播放| 日日日日日日日日夜夜夜夜夜夜| 国产精彩对白一区二区三区 | 亚洲国产欧美一区二区三区…| 亚洲国产最大av综合| 亚洲丝袜老师诱惑在线观看| 摧残蹂躏av一二三区| 国产中文精品在线观看| 偷拍自拍视频图片免费| 精品久久久久久久久久中文蒉 | 99热久久这里只有精品8| 成年女人免费播放视频| 不卡精品视频在线观看| 成人乱码一区二区三区av| 黄色成年网站午夜在线观看| 免费在线看的黄片视频| 亚洲天堂有码中文字幕视频 | 中文字幕一区二区人妻电影冢本| 色综合色综合色综合色| 一区二区三区欧美日韩高清播放| 亚洲在线一区二区欧美| 美女福利写真在线观看视频| 视频一区二区在线免费播放| 久久精品36亚洲精品束缚| 岛国黄色大片在线观看| 欧美视频中文一区二区三区| 一区二区三区四区视频| 久久精品国产999| 欧美 亚洲 另类综合| 福利午夜视频在线合集| 日本精品一区二区三区在线视频。| 亚洲的电影一区二区三区| 亚洲另类伦春色综合小| 亚洲卡1卡2卡三卡四老狼| 337p日本大胆欧美人| 亚洲高清国产一区二区三区| 日韩美av高清在线| 老司机99精品视频在线观看| 人妻丝袜av在线播放网址| 一区二区三区 自拍偷拍| 亚洲av男人天堂久久| 超碰公开大香蕉97| 亚洲 国产 成人 在线| 青青草人人妻人人妻| 亚洲欧美国产麻豆综合| 中国老熟女偷拍第一页| 99精品久久久久久久91蜜桃| 欧美亚洲免费视频观看| 日本精品视频不卡一二三| 在线免费91激情四射 | 日本xx片在线观看| 国产日韩欧美视频在线导航| 这里只有精品双飞在线播放| 亚洲伊人久久精品影院一美女洗澡| 玩弄人妻熟妇性色av少妇| 黄色大片免费观看网站| 欧美精品一区二区三区xxxx| 日韩精品一区二区三区在线播放| 亚洲欧美激情中文字幕| 日韩精品激情在线观看| 天天操天天干天天日狠狠插 | 91天堂精品一区二区| 午夜精品福利91av| 亚洲在线免费h观看网站| 粉嫩欧美美人妻小视频| 天天摸天天干天天操科普| 国产精品久久久久久久女人18| 国产精品国产三级麻豆| 青青青视频手机在线观看| 国际av大片在线免费观看| 日本性感美女写真视频| 亚洲精品一线二线在线观看 | avjpm亚洲伊人久久| 2022国产综合在线干| 97欧洲一区二区精品免费| 国产激情av网站在线观看| 国产露脸对白在线观看| 人人爽亚洲av人人爽av| 亚洲伊人av天堂有码在线| 最新国产精品网址在线观看| 国产密臀av一区二区三| av中文在线天堂精品| 国产精品自拍在线视频| 亚洲精品麻豆免费在线观看| 久久久久久久亚洲午夜综合福利| 日韩美在线观看视频黄| 99精品国自产在线人| 中文字幕免费在线免费| 午夜婷婷在线观看视频| 大屁股熟女一区二区三区| 91人妻精品一区二区久久| 日本xx片在线观看| 欧洲黄页网免费观看| 揄拍成人国产精品免费看视频| 在线观看av观看av| 三级黄色亚洲成人av| 污污小视频91在线观看| 精品国产午夜视频一区二区| 精品av久久久久久久| 青青青青青青草国产| 四川乱子伦视频国产vip| 亚洲国产美女一区二区三区软件| 久草视频 久草视频2| 欧美精品国产综合久久| mm131美女午夜爽爽爽| 午夜影院在线观看视频羞羞羞| 天天躁夜夜躁日日躁a麻豆| 香蕉av影视在线观看| av俺也去在线播放| 老司机福利精品视频在线| 少妇与子乱在线观看| 亚洲av极品精品在线观看| 护士小嫩嫩又紧又爽20p| 91欧美在线免费观看| 国产高潮无码喷水AV片在线观看 | 在线观看免费岛国av| 亚洲美女美妇久久字幕组| 欧美在线精品一区二区三区视频 | 最近中文字幕国产在线| 91啪国自产中文字幕在线| 欧美香蕉人妻精品一区二区| 1区2区3区不卡视频| 天堂av在线最新版在线| 久久精品在线观看一区二区| 中文字幕 人妻精品| 日韩av熟妇在线观看| 在线播放国产黄色av| 国产视频在线视频播放| 成人影片高清在线观看| 青青草精品在线视频观看| 任你操视频免费在线观看| 国产精品系列在线观看一区二区| 老鸭窝日韩精品视频观看| av中文字幕电影在线看| 亚洲综合色在线免费观看| 亚洲第一伊人天堂网| 久久久久久久亚洲午夜综合福利| 瑟瑟视频在线观看免费视频| 韩国黄色一级二级三级| 国产夫妻视频在线观看免费| 国产伊人免费在线播放| 国产 在线 免费 精品| av中文字幕在线观看第三页| 国产精品久久9999| 做爰视频毛片下载蜜桃视频1| 涩涩的视频在线观看视频| 任我爽精品视频在线播放| 日日夜夜精品一二三| 欧美另类重口味极品在线观看| 日本三极片视频网站观看| 又色又爽又黄的美女裸体| 大香蕉伊人国产在线| 亚洲成人av在线一区二区| 欧洲黄页网免费观看| 福利一二三在线视频观看| 蜜臀av久久久久久久| 国产污污污污网站在线| av中文在线天堂精品| 国产美女一区在线观看| 色综合天天综合网国产成人| 国产+亚洲+欧美+另类| 国产福利小视频二区| 激情五月婷婷免费视频| 99久久超碰人妻国产| 青青青视频自偷自拍38碰| 免费成人av中文字幕| 久久综合老鸭窝色综合久久| 天堂av狠狠操蜜桃| 青青在线视频性感少妇和隔壁黑丝 | 欧美美女人体视频一区| 国产成人无码精品久久久电影| 日韩成人免费电影二区| 精品国产午夜视频一区二区| 非洲黑人一级特黄片| 自拍偷拍亚洲精品第2页| 日韩av大胆在线观看| 亚洲综合另类精品小说| 91麻豆精品秘密入口在线观看| 大鸡吧插逼逼视频免费看 | 青青青青青青草国产| 欧美日韩一级黄片免费观看| 天堂av中文在线最新版| 日本欧美视频在线观看三区| 欧美特级特黄a大片免费| 插小穴高清无码中文字幕 | 岳太深了紧紧的中文字幕| 国产精品视频资源在线播放 | 亚洲综合一区二区精品久久| 99久久激情婷婷综合五月天| 亚洲一级美女啪啪啪| 伊人综合免费在线视频| 亚洲综合另类精品小说| 黄色片年轻人在线观看| 国产av一区2区3区| 在线观看视频污一区| 亚洲伊人av天堂有码在线| 久久久久国产成人精品亚洲午夜| 馒头大胆亚洲一区二区| 天天日天天透天天操| 丝袜肉丝一区二区三区四区在线看| 久久久久久9999久久久久| 护士特殊服务久久久久久久| tube69日本少妇| 人妻爱爱 中文字幕| 日本少妇在线视频大香蕉在线观看 | 中文字幕网站你懂的| 98精产国品一二三产区区别| 国产1区,2区,3区| 亚洲美女美妇久久字幕组| 国产成人精品一区在线观看 | 中文字幕一区二区三区人妻大片 | 日本高清在线不卡一区二区| 亚洲精品午夜久久久久| avjpm亚洲伊人久久| huangse网站在线观看| 成年人黄色片免费网站| 中文字幕一区二区人妻电影冢本| 天天日天天操天天摸天天舔| 国产午夜男女爽爽爽爽爽视频| 日韩三级黄色片网站| 97精品综合久久在线| 超碰97免费人妻麻豆| 这里有精品成人国产99| 黄色无码鸡吧操逼视频| 亚洲一区二区三区精品乱码| 欧美少妇性一区二区三区| 一区二区三区视频,福利一区二区| 五十路息与子猛烈交尾视频| 狠狠的往里顶撞h百合| 欧美色婷婷综合在线| av一本二本在线观看| 日韩三级电影华丽的外出| 在线免费观看视频一二区| www,久久久,com| 国产精品久久久久久久精品视频| 五色婷婷综合狠狠爱| 一区二区三区日韩久久| 国产一区二区欧美三区| 超pen在线观看视频公开97| 精品一区二区三四区| 亚洲一区二区三区在线高清| 午夜青青草原网在线观看| 五色婷婷综合狠狠爱| 97超碰免费在线视频| 骚逼被大屌狂草视频免费看| 日本人妻欲求不满中文字幕| 亚洲国产成人最新资源| 亚洲国产精品美女在线观看| 成年人该看的视频黄免费| 天天干天天日天天谢综合156| 亚洲免费国产在线日韩| 熟女在线视频一区二区三区| 在线播放 日韩 av| 岛国毛片视频免费在线观看| 欧美黄色录像免费看的| 日韩欧美国产一区ab| 欧美特级特黄a大片免费| 天堂av中文在线最新版| 偷拍美女一区二区三区| 亚洲av第国产精品| 天天日天天日天天擦| 最近的中文字幕在线mv视频| 日本女人一级免费片| 国产精品人妻一区二区三区网站| 亚洲另类图片蜜臀av| 性生活第二下硬不起来| 777奇米久久精品一区| 午夜精品九一唐人麻豆嫩草成人| 一本久久精品一区二区| 精品高跟鞋丝袜一区二区| 91久久综合男人天堂| 93视频一区二区三区| 女同互舔一区二区三区| 亚洲成人国产av在线| 国产精品黄片免费在线观看| 青青草在观免费国产精品| 国产chinesehd精品麻豆| 国产大学生援交正在播放| 三级等保密码要求条款| 欧美日韩在线精品一区二区三| 成人影片高清在线观看| h国产小视频福利在线观看| 欧美成人猛片aaaaaaa| 在线不卡成人黄色精品| 真实国模和老外性视频| 中文字幕奴隷色的舞台50| 激情五月婷婷免费视频| 这里只有精品双飞在线播放| 免费在线观看视频啪啪 | 2022国产综合在线干| 日韩欧美制服诱惑一区在线| 中国产一级黄片免费视频播放| 亚洲av琪琪男人的天堂| 中文字幕第一页国产在线| 超碰97人人澡人人| 国产极品精品免费视频| 2022国产精品视频| 黄页网视频在线免费观看| 日韩伦理短片在线观看| 亚洲av男人天堂久久| 国产老熟女伦老熟妇ⅹ| 99精品亚洲av无码国产另类| 天堂资源网av中文字幕| av一本二本在线观看| 久久精品美女免费视频| 91九色porny蝌蚪国产成人| 一区二区久久成人网| 老师让我插进去69AV| av资源中文字幕在线观看| 亚洲 中文 自拍 无码| 国产高清精品一区二区三区| 亚洲一区二区三区在线高清| 国产av福利网址大全| 国产乱子伦一二三区|