成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

java虛擬機(jī)的示例分析

這篇文章主要介紹了java虛擬機(jī)的示例分析,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

網(wǎng)站設(shè)計(jì)、成都網(wǎng)站設(shè)計(jì),成都做網(wǎng)站公司-成都創(chuàng)新互聯(lián)公司已向超過(guò)千家企業(yè)提供了,網(wǎng)站設(shè)計(jì),網(wǎng)站制作,網(wǎng)絡(luò)營(yíng)銷(xiāo)等服務(wù)!設(shè)計(jì)與技術(shù)結(jié)合,多年網(wǎng)站推廣經(jīng)驗(yàn),合理的價(jià)格為您打造企業(yè)品質(zhì)網(wǎng)站。

1.前言(基于JDK1.7)  

所謂jvm,又名java虛擬機(jī)。我們平常寫(xiě)java程序的時(shí)候幾乎是感覺(jué)不到j(luò)vm的存在的,我們只需要根據(jù)java規(guī)范去編寫(xiě)類(lèi),然后就可以運(yùn)行程序了,當(dāng)然只有我們程序出現(xiàn)bug了,我們才有可能在控制臺(tái)上看到一些jvm報(bào)錯(cuò)的信息,比如內(nèi)存溢出異常等。

java之所以能夠跨平臺(tái),就是因?yàn)閖vm屏蔽了各個(gè)操作系統(tǒng)之間的差異,舉個(gè)形象的例子,我們手機(jī)要充電吧,但是充電的方式有很多種,你可以直接數(shù)據(jù)線插到插座充電,也可以用數(shù)據(jù)線插到電腦USB口充電,一個(gè)是電腦一個(gè)是插座,為什么都能給手機(jī)充電呢?原因就是有數(shù)據(jù)線屏蔽了插座和電腦的差異,對(duì)于手機(jī)來(lái)說(shuō),它是看不到數(shù)據(jù)線另外一頭連接的是什么設(shè)備,只知道有電通過(guò)數(shù)據(jù)線向自己傳過(guò)來(lái)就ok了,順便一提,這也是所謂的適配器的原理!

開(kāi)始之前首先要明確一點(diǎn),每一個(gè)java程序運(yùn)行就會(huì)創(chuàng)建一個(gè)jvm實(shí)例!比如我同時(shí)在eclipse中同時(shí)運(yùn)行三個(gè)程序,那么就會(huì)創(chuàng)建三個(gè)jvm實(shí)例,三個(gè)程序運(yùn)行于自己的jvm中,互不干擾,當(dāng)程序運(yùn)行完畢,那么jvm也會(huì)銷(xiāo)毀。

2.簡(jiǎn)單看看類(lèi)加載過(guò)程

大家知道一個(gè)類(lèi)加載到j(luò)vm大概是經(jīng)過(guò)了幾個(gè)步驟的吧!編譯成字節(jié)碼文件,加載,鏈接(驗(yàn)證,準(zhǔn)備,解析),初始化....,我就簡(jiǎn)單的用下面這個(gè)圖一起看看;

java虛擬機(jī)的示例分析

在這里,我們重點(diǎn)看看字節(jié)碼文件到j(luò)vm這一段,為什么字節(jié)碼文件能夠被加載到j(luò)vm中呢?類(lèi)加載器又是什么呢?加載的具體過(guò)程又是什么呢?鏈接,初始化又具體的是在做些什么事呢?Class對(duì)象又是什么鬼?jvm中的具體結(jié)構(gòu)又是什么樣子的,各有什么用處?假如執(zhí)行一個(gè)類(lèi)中的方法,在jvm中到底是什么流程呢?等等很多問(wèn)題

這些問(wèn)題有的是了解一點(diǎn),有的是真不知道,反正就是迷迷糊糊的一個(gè)類(lèi)就加載成功了,然后我們就能成功調(diào)用那些方法了,平常用起來(lái)很舒服,但是細(xì)細(xì)想來(lái)難道不覺(jué)得奇怪嗎?

反正我最初看到j(luò)vm的時(shí)候,最想吐槽的一句話(huà)就是:瑪?shù)?,為什么啊?我感覺(jué)我已經(jīng)要化身成十萬(wàn)個(gè)為什么了,咳咳,不說(shuō)廢話(huà)了,開(kāi)始往后學(xué)吧!

下面我大概說(shuō)一下這些步驟到底是做了什么事,有個(gè)大概的流程,然后我們慢慢的深入探究每一個(gè)步驟到底是干了什么事!

2.1 編譯器編譯

這個(gè)沒(méi)什么好說(shuō)的,由于java是靜態(tài)語(yǔ)言,在執(zhí)行java程序之前會(huì)先把我們寫(xiě)的java文件給轉(zhuǎn)化成特殊的二進(jìn)制碼的形式,編譯器就是做這個(gè)轉(zhuǎn)化的工作的工具,而且在我們寫(xiě)代碼的時(shí)候,還沒(méi)運(yùn)行程序之前,就會(huì)報(bào)錯(cuò),在某處代碼下面會(huì)有紅線標(biāo)識(shí),做這個(gè)工作的就是編譯器,還有最重要的源文件中泛型,是會(huì)在編譯器編譯這個(gè)階段就會(huì)進(jìn)行擦除,所以字節(jié)碼文件中是沒(méi)有任何泛型信息的;

順便提一下動(dòng)態(tài)語(yǔ)言,比如Python,我們寫(xiě)一個(gè)python程序運(yùn)行,是不需要進(jìn)行編譯的,會(huì)讀取第一行源文件中代碼就運(yùn)行這一行的代碼,然后讀取第二行代碼,運(yùn)行第二行代碼...

2.2 類(lèi)加載器的分類(lèi)和加載順序

什么是類(lèi)加載器呢?我有一個(gè)很生動(dòng)很形象的例子:假如字節(jié)碼文件是一個(gè)人,而jvm就是地府,你說(shuō)人死了會(huì)怎么進(jìn)入地府呢?自己肯定找不到地府的位置,于是要讓黑白無(wú)常請(qǐng)你過(guò)去了,類(lèi)加載器在這里就是黑白無(wú)常!

大概了解類(lèi)加載器的用處之后,我們就隨意看看類(lèi)加載器的種類(lèi)和運(yùn)行原理;

順便提一下,我們還記得最開(kāi)始配置的jdk環(huán)境變量吧!我的JAVA_HOME=D:\java\jdk1.7;

話(huà)說(shuō)大家知道jar包到底是什么嗎?其實(shí)就是一種壓縮文件的格式,跟zip,gz等壓縮格式?jīng)]有多大區(qū)別,可以用360壓縮打開(kāi)。。。

進(jìn)入正題,類(lèi)加載器分為四種,啟動(dòng)類(lèi)加載器(Bootstrap ClassLoader):最頂級(jí)的類(lèi)加載器,還是用C++寫(xiě)的;在我們編寫(xiě)java程序的時(shí)候,編譯器會(huì)自動(dòng)的幫我們導(dǎo)入一下常用的jar包,用的就是這個(gè)類(lèi)加載器,比如我們最熟悉的lang包下的Object,String,Integer等都是我們可以直接用的,而不需要我們手動(dòng)導(dǎo)入;具體的會(huì)導(dǎo)入哪些jar包呢,這就需要我們配置環(huán)境變量JAVA_HOME,編譯器會(huì)去環(huán)境變量中找%JAVA_HOME%\jre\lib ,這下面所有jar包然后進(jìn)行加載到內(nèi)存中,注意不是加載在JVM中;而且出于安全考慮,啟動(dòng)類(lèi)加載器只加載包名為java、javax、sun等開(kāi)頭的類(lèi)

擴(kuò)展類(lèi)加載器(Extension ClassLoader):父類(lèi)加載器是啟動(dòng)類(lèi)加載器,java語(yǔ)言實(shí)現(xiàn),負(fù)責(zé)加載%JAVA_HOME%\jre\lib\ext 路徑下的jar包,這個(gè)不會(huì)自動(dòng)加載,只有在需要加載的時(shí)候才去加載。

應(yīng)用類(lèi)加載器(Application ClassLoader):父類(lèi)加載器是擴(kuò)展類(lèi)加載器,java語(yǔ)言實(shí)現(xiàn),也可以叫做系統(tǒng)類(lèi)加載器(System ClassLoader),這個(gè)類(lèi)加載器主要是加載我們?cè)趯?xiě)項(xiàng)目時(shí)編寫(xiě)的放在類(lèi)路徑下的類(lèi),比如maven項(xiàng)目中src/main/java/所有類(lèi)

自定義類(lèi)加載器:需要我們自己實(shí)現(xiàn),當(dāng)特殊情況下我們需要自定義類(lèi)加載器,只需要實(shí)現(xiàn)ClassLoader接口,然后重寫(xiě)findClass()方法,我們就能夠自己實(shí)現(xiàn)一個(gè)類(lèi)加載器,而且自己實(shí)現(xiàn)類(lèi)加載器之后可以去加載任何地方的類(lèi)。假如我新建一個(gè)類(lèi)放在F盤(pán)的隨便一個(gè)角落里也可以指定類(lèi)路徑去加載,有興趣的小伙伴可以去試試。

不考慮自定義類(lèi)加載器,可以看到,啟動(dòng)、擴(kuò)展、應(yīng)用這三個(gè)加載器就像是爺爺,爸爸,兒子一樣的關(guān)系,所以要加載一個(gè)類(lèi)的話(huà),選用哪個(gè)類(lèi)加載器呢?肯定是有什么好吃的先讓兒子吃呀,然而兒子又很有孝心,會(huì)把到手的好吃的給爸爸吃。爸爸又會(huì)給爺爺吃,爺爺會(huì)嘗試著吃,假如一看這東西糖分太高于是就又給爸爸吃,爸爸也嘗試著吃,發(fā)現(xiàn)這東西不好吃,于是最后還是給兒子吃....這就是類(lèi)加載器的雙親委托機(jī)制,隨便找了一幅圖看看:

java虛擬機(jī)的示例分析

2.3.JVM內(nèi)部結(jié)構(gòu)

其實(shí)大多數(shù)人對(duì)JVM是很熟悉了,不就是那幾個(gè)塊嗎?本地方法棧,java棧,java堆,方法區(qū),pc計(jì)數(shù)器,我這里就先大概說(shuō)一下這幾個(gè)部分的用處;

java虛擬機(jī)的示例分析

方法區(qū):類(lèi)加載器其實(shí)就是將字節(jié)碼文件給丟到這里,并解析出字節(jié)碼文件中包含的一些信息,比如全類(lèi)名,類(lèi)變量,方法有關(guān)的信息,父類(lèi)信息,是不是接口等等這類(lèi)信息

由于方法區(qū)很重要,我就隨意畫(huà)個(gè)草圖:

java虛擬機(jī)的示例分析

常量池(屬于方法區(qū)):由于方法區(qū)比較厲害能把字節(jié)碼文件中很多信息給解析出來(lái),但其中可能有很多常量比如18,“helloworld”,以及一些符號(hào)引用,常量池就存這些東西;但是什么又是符號(hào)引用呢?我就大概說(shuō)一下吧,假如兩個(gè)類(lèi)Animal和Dog,在Animal類(lèi)中有個(gè)方法里面是這樣的:Dog dog = new Dog();dog.run(); 這個(gè)時(shí)候問(wèn)題來(lái)了,在加載Animal類(lèi)的時(shí)候發(fā)現(xiàn)了要用到Dog類(lèi),肯定是要去加載Dog類(lèi)的,那么有兩種做法,第一種先暫停Animal類(lèi)的加載去加載Dog類(lèi),加載完之后再加載Dog類(lèi),第二種,Animal類(lèi)繼續(xù)加載的同時(shí)順便加載Dog類(lèi),只是Animal中只要是用到了Dog類(lèi)、方法、字段的所有地方我隨便用xxx來(lái)表示,等Dog類(lèi)加載完之后我再把xxx指向方法區(qū)Dog類(lèi)對(duì)應(yīng)的地址就ok了;我們當(dāng)然用第二種方法啦,并且在這里我們隨便用的xxx就是符號(hào)引用,而加載完成后方法區(qū)中的Dog類(lèi)地址就是直接引用

java堆:根據(jù)方法區(qū)中存的這么豐富的信息,這里就會(huì)創(chuàng)建每一個(gè)類(lèi)的Class對(duì)象,話(huà)說(shuō)這個(gè)Class對(duì)象用的最多的就是反射,那么這個(gè)Class對(duì)象到底是個(gè)什么呢?其實(shí)不用想的太難理解了,你就把它看作字節(jié)碼文件在內(nèi)存中的另外一種形式唄,就好像大米,在電飯煲里的表現(xiàn)形式就是米飯,在高壓鍋里的表現(xiàn)形式就是粥了.....;假如程序運(yùn)行的話(huà),還會(huì)在堆中創(chuàng)建對(duì)象并且存放在堆中,所有的同類(lèi)型的類(lèi)的實(shí)例對(duì)象共享一個(gè)Class對(duì)象,我也隨意畫(huà)了一個(gè)草圖來(lái)看看如下所示,所以同一個(gè)類(lèi)的不同實(shí)例對(duì)象的xx.getClass()都是一樣的,而且根據(jù)獲得的Class對(duì)象可以利用反射創(chuàng)建新的對(duì)象和獲取其中的方法,可以說(shuō)Class對(duì)象為我們程序員提供了一個(gè)操作堆中對(duì)象的一個(gè)安全通道

java虛擬機(jī)的示例分析

pc寄存器:對(duì)于多線程來(lái)說(shuō),你就可以把這個(gè)看作一個(gè)計(jì)數(shù)器,每個(gè)線程一個(gè),里面寫(xiě)著1,2,3,4,5....記錄著各個(gè)線程執(zhí)行代碼的行號(hào),為什么要記這個(gè)行號(hào)呢?莫非是閑的蛋疼?當(dāng)然不是!因?yàn)閷?duì)于多線程來(lái)說(shuō),cpu首先執(zhí)行一號(hào)線程,然后停止,去執(zhí)行二號(hào)線程,又停止,又去執(zhí)行一號(hào)線程...這個(gè)時(shí)候問(wèn)題來(lái)了,cpu怎么知道上一次一號(hào)線程執(zhí)行到哪里來(lái)了?于是啊,這個(gè)pc寄存器用處就來(lái)了,因?yàn)槊總€(gè)線程都有一個(gè),而且記錄著當(dāng)前執(zhí)行的行號(hào),下次cpu來(lái)了根據(jù)這個(gè)行號(hào)就可以接著執(zhí)行了??!

java棧:對(duì)象已經(jīng)創(chuàng)建完畢放在堆中,然后我們調(diào)用一個(gè)java方法,就會(huì)在java棧中開(kāi)辟一小塊空間(就是所謂的壓棧),俗稱(chēng)棧幀,棧幀可以有多個(gè),因?yàn)橐粋€(gè)方法中可以調(diào)用其他方法嘛!總之一個(gè)方法就對(duì)應(yīng)一個(gè)棧幀,棧幀里面放著我們這個(gè)要運(yùn)行方法內(nèi)的局部變量,方法返回值等等參數(shù),等這個(gè)方法執(zhí)行完之后這個(gè)棧幀就退出去了(這就是所謂的彈棧),然后棧就恢復(fù)原樣

本地方法棧:不知道大家有沒(méi)有打開(kāi)JDK的一些類(lèi)的源碼看看,很多類(lèi)都有Native方法(本地方法),我的理解是就是調(diào)用操作系統(tǒng)中一些c語(yǔ)言實(shí)現(xiàn)的方法或者其他語(yǔ)言實(shí)現(xiàn)的方法....

2.4.加載

說(shuō)了這么久的類(lèi)加載器的種類(lèi)還有類(lèi)加載器的使用順序,然后也簡(jiǎn)單說(shuō)了JVM內(nèi)部結(jié)構(gòu)以及各自的作用,現(xiàn)在就是選好了的類(lèi)加載器去加載字節(jié)碼文件丟到JVM中的方法區(qū)中了。

用偽代碼隨便看看加載大概步驟,參數(shù)name就是我們傳進(jìn)去的類(lèi)的全名:

public Class<?> loadClass(String name) { 
 try { 
  if (parent != null) { 
  //如果存在父類(lèi)加載器,就委派給父類(lèi)加載器加載 
  c = parent.loadClass(name, false); 
  } else { 
  //如果不存在父類(lèi)加載器,就檢查是否是由啟動(dòng)類(lèi)加載器加載的類(lèi), 通過(guò)調(diào)用本地方法native findBootstrapClass0
  c = findBootstrapClass0(name); 
  } 
 } catch (ClassNotFoundException e) { 
  // 如果父類(lèi)加載器和啟動(dòng)類(lèi)加載器都不能完成加載任務(wù),才調(diào)用自身的加載功能 
  c = findClass(name); 
 }

所以假如我自定義一個(gè)類(lèi)加載器MyClassLoader,那么就可以用這種方式去加載我隨意放在F盤(pán)myclass目錄里面,com.wyq.test包下的一個(gè)Student類(lèi):

MyClassLoader myClassLoader=new MyClassLoader("F:\\myclass");
Class c=myClassLoader.loadClass("com.wyq.test.Student");

然后我們得到了這個(gè)類(lèi)的Class對(duì)象就可以用反射對(duì)這個(gè)類(lèi)為所欲為了,嘿嘿嘿嘿~

2.5.鏈接

鏈接中分為三步:驗(yàn)證,準(zhǔn)備,解析;

隨便說(shuō)說(shuō)這三步大概干些什么,驗(yàn)證:這一步其實(shí)沒(méi)什么大的用處,就是虛擬機(jī)會(huì)檢查一下我們的字節(jié)碼文件有沒(méi)有問(wèn)題,具體的就是看看你字節(jié)碼文件格式有問(wèn)題嗎?語(yǔ)法有沒(méi)有問(wèn)題?等等

準(zhǔn)備:給類(lèi)的靜態(tài)變量分配內(nèi)存空間,并設(shè)置初始值;大家都知道靜態(tài)變量是放在方法區(qū)中的吧,比如我java類(lèi)中有個(gè)靜態(tài)變量static int age = 18 那么這這個(gè)階段首先會(huì)分配4個(gè)字節(jié)的內(nèi)存空間,然后設(shè)置初始值為0,八大基本數(shù)據(jù)類(lèi)型都有初始值,可以了解了解

解析:比較專(zhuān)業(yè)一點(diǎn)的說(shuō)法就是,在解析階段,JVM會(huì)把類(lèi)的二進(jìn)制數(shù)據(jù)中的符號(hào)引用替換為直接引用!這句話(huà)怎么理解請(qǐng)看上面介紹的常量池

2.6 初始化

還是用準(zhǔn)備階段那個(gè)靜態(tài)變量,根據(jù)字節(jié)碼文件,將準(zhǔn)備那個(gè)階段的初始值覆蓋成真正的值18;

順便說(shuō)一句,加載、鏈接、初始化三個(gè)步驟不是一定要按照這個(gè)順序完成的,只是開(kāi)始的順序是這個(gè),但是在執(zhí)行過(guò)程中可能會(huì)有彎道超車(chē)的現(xiàn)象

3.例子分析

這里我們寫(xiě)一個(gè)最簡(jiǎn)單的例子來(lái)總結(jié)一下上面這么多知識(shí);

public class Animal{
 private int age=18;
 public void run() {} 

}

publci class Test{
 public static void main(String[] args){
 Animal animal = new Animal();
 animal.run();

 }
}

運(yùn)行這個(gè)main方法的步驟:

1.首先是編譯器會(huì)將這兩個(gè)類(lèi)都編譯成字節(jié)碼文件并放在你的項(xiàng)目存放路徑

2.Test這個(gè)類(lèi)會(huì)以某種方式告訴JVM自己的類(lèi)名“Test”,虛擬機(jī)就會(huì)以某種牛逼的方法可以找到你這個(gè)Test.class放在那個(gè)目錄下面

3.調(diào)用類(lèi)加載器,采用雙親委托機(jī)制去加載這個(gè)類(lèi),最后不出意外應(yīng)該是應(yīng)用類(lèi)加載器去加載這個(gè)Test.class,以二進(jìn)制流的形式加載進(jìn)JVM方法區(qū)

4.在加載之后會(huì)去驗(yàn)證這個(gè)Test.class是否符合規(guī)范,沒(méi)問(wèn)題的話(huà)就會(huì)解析這個(gè)加載進(jìn)來(lái)的Test.class,將其中很多信息都保存下來(lái),常量和符號(hào)引用保存在常量池中,其他的比如訪問(wèn)修飾符,全類(lèi)名,直接父類(lèi)的全類(lèi)名,方法和字段信息,除了常量以外的所有靜態(tài)變量,以及指向類(lèi)加載器和Class對(duì)象的指針等都存在常量池外面

5.通過(guò)保存在方法區(qū)中的字節(jié)碼,JVM可以執(zhí)行main()方法,在執(zhí)行這個(gè)方法的時(shí)候,會(huì)一直持有有一個(gè)指向Test的常量池的指針;

6.在執(zhí)行main方法的第一條指令的時(shí)候,就是告訴JVM為T(mén)est常量池的第一個(gè)類(lèi)型分配足夠內(nèi)存;由于main方法一直持有執(zhí)行Test常量池指針于是很迅速的找到了常量池第一項(xiàng),發(fā)現(xiàn)它是一個(gè)對(duì)Animal類(lèi)的符號(hào)引用,然后就會(huì)先檢查方法區(qū)看有沒(méi)有Animal類(lèi)有沒(méi)有被加載,假如沒(méi)有的話(huà)就要去找到這個(gè)Animal類(lèi);這里就有了一個(gè)算法的小知識(shí),怎么才能夠讓虛擬機(jī)最快速度找到Animal類(lèi)所在位置呢?可以用散列表,搜索樹(shù)等算法。

7.加載Animal.class到方法區(qū)并提取其中有用的信息保存在方法區(qū),然后替換Test常量池第一個(gè)類(lèi)型的符號(hào)引用,變?yōu)橹苯右茫蛔⒁?,這個(gè)時(shí)候還沒(méi)有創(chuàng)建對(duì)象,直接引用指向的是方法區(qū)中Animal所在的地址

8.JVM在堆中為創(chuàng)建Animal對(duì)象分配足夠內(nèi)存,怎么確定這個(gè)內(nèi)存多大合適呢?其實(shí)JVM比較牛,已經(jīng)設(shè)好了可以根據(jù)方法區(qū)中存放的信息確定一個(gè)類(lèi)創(chuàng)建對(duì)象要用到多少堆空間;

9.對(duì)象創(chuàng)建好了會(huì)設(shè)置Animal實(shí)例變量的默認(rèn)初始值:age = 0

10.創(chuàng)建一個(gè)棧幀(里面有一個(gè)指向Animal對(duì)象的引用),壓入java棧中,到此main方法第一條指令就執(zhí)行完畢;還記得一個(gè)方法一個(gè)棧幀么

11.然后根據(jù)這個(gè)棧幀調(diào)用java代碼,將age的值初始化為正確的值:18

12.通過(guò)這個(gè)棧幀執(zhí)行run()方法,又會(huì)開(kāi)辟一個(gè)棧幀存放run()方法內(nèi)部的所有信息

13.run()方法執(zhí)行完畢,釋放這個(gè)棧幀;然后main()執(zhí)行完畢,釋放棧幀;然后就是程序執(zhí)行完畢,清理回收堆中所有對(duì)象以及方法區(qū)

大概就是這么一個(gè)流程,其中最后的那個(gè)清理回收過(guò)程其實(shí)很重要,由于java棧和方法區(qū)的清理內(nèi)存效率非常好,我們可以不用在意,重點(diǎn)是在堆中清理內(nèi)存,而且由于有的程序是會(huì)運(yùn)行很久的,不可能每次都等程序執(zhí)行完畢之后再一起清理,肯定是要一邊運(yùn)行程序一邊清理堆內(nèi)存中沒(méi)用的對(duì)象,那么又該怎么進(jìn)行處理呢?又會(huì)涉及到很多的算法以及堆內(nèi)部到底是什么結(jié)構(gòu),后面我們會(huì)逐漸挖掘...

感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“java虛擬機(jī)的示例分析”這篇文章對(duì)大家有幫助,同時(shí)也希望大家多多支持創(chuàng)新互聯(lián),關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來(lái)學(xué)習(xí)!

分享名稱(chēng):java虛擬機(jī)的示例分析
標(biāo)題鏈接:http://jinyejixie.com/article44/podiee.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供App設(shè)計(jì)、做網(wǎng)站、面包屑導(dǎo)航、品牌網(wǎng)站設(shè)計(jì)、外貿(mào)網(wǎng)站建設(shè)商城網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

微信小程序開(kāi)發(fā)
乐至县| 通辽市| 五指山市| 义马市| 大庆市| 蒲城县| 上犹县| 微山县| 盖州市| 嘉峪关市| 华蓥市| 资阳市| 沭阳县| 平陆县| 宝坻区| 京山县| 阿巴嘎旗| 敖汉旗| 黄冈市| 隆德县| 平阴县| 阜平县| 海安县| 邵阳市| 湟中县| 三都| 和顺县| 天峨县| 什邡市| 中超| 兴化市| 海安县| 长丰县| 大宁县| 台湾省| 西贡区| 水城县| 如东县| 馆陶县| 蓝田县| 湘潭市|