国产午夜男女在线|欧美日本一道高清国产|亚洲日韩乱码中文字幕|麻豆国产97在线精品一区|日韩一区2区三区另类图片|亚洲精品国产99在线观看|亚洲国产午夜福利精品大秀在线|一级做a爰片性色毛片免费网站

您當(dāng)前的位置 :寧夏資訊網(wǎng) > 微商 >  內(nèi)容正文
投稿

Java的類加載器與雙親委托機(jī)制

寧夏資訊網(wǎng) 2020-03-30 19:59:30 來源: 閱讀:-

目錄:

  • 類加載器
  • java.lang.ClassLoader類 URLClassLoader與SecureClassLoader ClassLoader常見方法源碼分析
  • 雙親委托機(jī)制 圖解 源碼角度分析
  • 常見的問題分析

前言:我們剛剛接觸Java時(shí),在IDE(集成開發(fā)環(huán)境) 或者文本編輯器中所寫的都是.java文件,在編譯后會(huì)生成.class文件,又稱字節(jié)碼文件。

javac HelloWorld.java ---> HelloWorld.class 復(fù)制代碼

對(duì)于.class文件來說,需要被加載到虛擬機(jī)中才能使用,這個(gè)加載的過程就成為類加載。如果想要知道類加載的方式,就需要知道類加載器雙親委托機(jī)制的概念。也就是我們本篇所要介紹的內(nèi)容。

1. 類加載器

Java中的類加載器可以分為兩種:

  • 系統(tǒng)類加載器
  • 自定義類加載器

而系統(tǒng)類加載器又有3個(gè):

  • Bootstrap ClassLoader:?jiǎn)?dòng)類加載器
  • Extensions ClassLoader:擴(kuò)展類加載器
  • App ClassLoader:也稱為SystemAppClass,系統(tǒng)類加載器

1.1 Bootstrap ClassLoader

Bootstrap ClassLoader用來加載JVM(Java虛擬機(jī))運(yùn)行時(shí)所需要的系統(tǒng)類,其使用c++實(shí)現(xiàn)。

從以下路徑來加載類:

  1. %JAVA_HOME%/jre/lib目錄,如rt.jar、resources.jar、charsets.jar等
  2. 可以在JVM啟動(dòng)時(shí),指定-Xbootclasspath參數(shù),來改變Bootstrap ClassLoader的加載目錄。

Java虛擬機(jī)的啟動(dòng)就是通過 Bootstrap ClassLoader創(chuàng)建一個(gè)初始類來完成的。 可以通過如下代碼來得出Bootstrap ClassLoader所加載的目錄:

public class ClassLoaderTest {    public static void main(String[]args) {        System.out.println(System.getProperty("sun.boot.class.path"));    }}復(fù)制代碼

打印結(jié)果為:

C:\Program Files\Java\jdk1.8.0_102\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_102\jre\lib\rt.jar;C:\Program Files\Java\jdk1.8.0_102\jre\lib\sunrsasign.jar;C:\Program Files\Java\jdk1.8.0_102\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_102\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_102\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_102\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_102\jre\classes復(fù)制代碼

可以發(fā)現(xiàn)幾乎都是$JAVA_HOME/jre/lib目錄中的jar包,包括rt.jar、resources.jar和charsets.jar等等。

1.2 Extensions ClassLoader

Extensions ClassLoader(擴(kuò)展類加載器)具體是由ExtClassLoader類實(shí)現(xiàn)的,ExtClassLoader類位于sun.misc.Launcher類中,是其的一個(gè)靜態(tài)內(nèi)部類。對(duì)于Launcher類,可以先看成是Java虛擬機(jī)的一個(gè)入口。

ExtClassLoader的部分代碼如下:


Extensions ClassLoader負(fù)責(zé)將JAVA_HOME/jre/lib/ext或者由系統(tǒng)變量-Djava.ext.dir指定位置中的類庫(kù)加載到內(nèi)存中。

通過以下代碼可以得到Extensions ClassLoader加載目錄:

System.out.println(System.getProperty("java.ext.dirs"));復(fù)制代碼

打印結(jié)果為:

C:\Program Files\Java\jdk1.8.0_102\jre\lib\ext;C:\Windows\Sun\Java\lib\ext復(fù)制代碼

1.3 App ClassLoader

也稱為SystemAppClass(系統(tǒng)類加載器),具體是由AppClassLoader類實(shí)現(xiàn)的,AppClassLoader類也位于sun.misc.Launcher類中。

部分代碼如下:


  1. 主要加載Classpath目錄下的的所有jar和Class文件,是程序中的默認(rèn)類加載器。這里的Classpath是指我們Java工程的bin目錄。
  2. 也可以加載通過-Djava.class.path選項(xiàng)所指定的目錄下的jar和Class文件。

通過以下代碼可以得到App ClassLoader加載目錄:

System.out.println(System.getProperty("java.class.path"));復(fù)制代碼

打印結(jié)果為:

C:\workspace\Demo\bin復(fù)制代碼

這個(gè)路徑其實(shí)就是當(dāng)前Java工程目錄bin,里面存放的是編譯生成的class文件。


在Java中,除了上述的3種系統(tǒng)提供的類加載器,還可以自定義一個(gè)類加載器。

1.4. 自定義類加載器

為了可以從指定的目錄下加載jar包或者class文件,我們可以用繼承java.lang.ClassLoader類的方式來實(shí)現(xiàn)一個(gè)自己的類加載器。

在自定義類加載器時(shí),我們一般復(fù)寫findClass方法,并在findClass方法中調(diào)用defineClass方法。

接下來會(huì)先介紹下ClassLoader類相關(guān)的具體內(nèi)容,之后看一個(gè)自定義類加載器demo。

2 java.lang.ClassLoader類

2.1 ClassLoader、URLClassLoader與SecureClassLoader的關(guān)系

從上面關(guān)于ExtClassLoader、AppClassLoader源碼圖中我們可以看到,他們都繼承自URLClassLoader,那這個(gè)URLClassLoader是什么,其背后又有什么呢?

先來一張很重要的繼承關(guān)系圖:


  • ClassLoader是一個(gè)抽象類,位于java.lang包下,其中定義了ClassLoader的主要功能。
  • SecureClassLoader繼承了抽象類ClassLoader,但SecureClassLoader并不是ClassLoader的實(shí)現(xiàn)類,而是拓展了ClassLoader類加入了權(quán)限方面的功能,加強(qiáng)了ClassLoader的安全性。
  • URLClassLoader繼承自SecureClassLoader,用來通過URl路徑從jar文件和文件夾中加載類和資源。
  • ExtClassLoader和AppClassLoader都繼承自URLClassLoader,它們都是Launcher 的內(nèi)部類,Launcher 是Java虛擬機(jī)的入口應(yīng)用,ExtClassLoader和AppClassLoader都是在Launcher中進(jìn)行初始化的。

2.2 普通的類、AppClassLoader與ExtClassLoader之間的關(guān)系

關(guān)系:

  • 加載普通的類(這里指得是我們所編寫的代碼類,下文demo中的Test類)加載器是AppClassLoader,AppClassLoader的父加載器為ExtClassLoader
  • 而ExtClassLoader的父加載器是Bottstrap ClassLoader

還有2個(gè)結(jié)論:

  • 每個(gè)類都有類加載器
  • 每個(gè)類加載器都有父加載器

我們準(zhǔn)備一個(gè)簡(jiǎn)單的demo 自建的一個(gè)Test.java文件。

public class Test{}復(fù)制代碼
public class Main {    public static void main(String[] args) {ClassLoader cl = Test.class.getClassLoader();System.out.println("ClassLoader is:"+cl.toString());}}復(fù)制代碼

這樣就可以獲取到Test.class文件的類加載器,然后打印出來。結(jié)果是:

sun.misc.Launcher$AppClassLoader@75b83e92復(fù)制代碼

也就是說明Test.class文件是由AppClassLoader加載的。

那AppClassLoader是誰加載的呢? 其實(shí)AppClassLoader也有一個(gè)父加載器,我們可以通過以下代碼獲取

public class Test {    public static void main(String[] args) {        ClassLoader loader = Test.class.getClassLoader();        while (loader != null) {            System.out.println(loader);            loader = loader.getParent();        }    }}復(fù)制代碼

上述代碼結(jié)果如下:

sun.misc.Launcher$AppClassLoader@7565783bsun.misc.Launcher$ExtClassLoader@1b586d23復(fù)制代碼
  • 加載Test的類加載器是AppClassLoader,AppClassLoader的父加載器為ExtClassLoader
  • 而ExtClassLoader的父加載器是Bottstrap ClassLoader

至于為何沒有打印出ExtClassLoader的父加載器Bootstrap ClassLoader,這是因?yàn)锽ootstrap ClassLoader是由C++編寫的,并不是一個(gè)Java類,因此我們無法在Java代碼中獲取它的引用。

2.3 java.lang.ClassLoader類常見的方法

上一節(jié)我們看到了ClassLoader的getParent方法,getParent獲取到的其實(shí)就是其父加載器。這一節(jié)將通過源碼,來介紹ClassLoader中的一些重要方法。

getParent()
ClassLoader類---------public final ClassLoader getParent() {    if (parent == null) return null;    SecurityManager sm = System.getSecurityManager();    if (sm != null) {        checkClassLoaderPermission(parent, Reflection.getCallerClass());    }    return parent;}復(fù)制代碼

我們可以看到,其返回值有兩種可能,為空或者是parent變量。

從源碼中還可以發(fā)現(xiàn)其是一個(gè)final修飾的方法,我們知道被final修飾的說明這個(gè)方法提供的功能已經(jīng)滿足當(dāng)前要求,是不可以重寫的, 所以其各個(gè)子類所調(diào)用的getParent()方法最終都會(huì)由ClassLoader來處理。

parent變量又是什么呢?我們?cè)诓榭丛创a時(shí)可以發(fā)現(xiàn)parent的賦值是在構(gòu)造方法中。

ClassLoader類---------private ClassLoader(Void unused, ClassLoader parent) {    this.parent = parent;    ... //省略了無關(guān)代碼}復(fù)制代碼

而此構(gòu)造方法又是私有的,不能被外部調(diào)用,所以其調(diào)用者還是在內(nèi)部。于是接著查找到了另外兩個(gè)構(gòu)造方法。

ClassLoader類---------protected ClassLoader() {    this(checkCreateClassLoader(), getSystemClassLoader());}    protected ClassLoader(ClassLoader parent) {    this(checkCreateClassLoader(), parent);}復(fù)制代碼

所以:

  1. 可以在調(diào)用ClassLoder的構(gòu)造方法時(shí),指定一個(gè)parent。
  2. 若沒有指定的話,會(huì)使用getSystemClassLoader()方法的返回值。

接著看上面代碼中的getSystemClassLoader的源碼:

ClassLoader類---------public static ClassLoader getSystemClassLoader() {    initSystemClassLoader();    if (scl == null) {        return null;    }    SecurityManager sm = System.getSecurityManager();    if (sm != null) {        checkClassLoaderPermission(scl, Reflection.getCallerClass());    }    return scl;}復(fù)制代碼

其返回的是一個(gè)scl。在initSystemClassLoader()方法中發(fā)現(xiàn)了對(duì)scl變量的賦值。

ClassLoader類---------private static synchronized void initSystemClassLoader() {    if (!sclSet) {        if (scl != null)            throw new IllegalStateException("recursive invocation");        sun.misc.Launcher l = sun.misc.Launcher.getLauncher(); //1        if (l != null) {            Throwable oops = null;            scl = l.getClassLoader();            ...//省略代碼        }        sclSet = true;    }}復(fù)制代碼

重點(diǎn)來了,注釋1處其獲取到的是Launcher類的對(duì)象,然后調(diào)用了Launcher類的getClassLoader()方法。

Launcher類---------public ClassLoader getClassLoader() {    return this.loader;}復(fù)制代碼

那這個(gè)this.loader是什么呢?在Launcher類中發(fā)現(xiàn),其賦值操作在Launcher的構(gòu)造方法中,其值正是Launcher類中的AppClassLoader

Launcher類---------public Launcher() {    Launcher.ExtClassLoader var1;    try {        var1 = Launcher.ExtClassLoader.getExtClassLoader();    } catch (IOException var10) {        throw new InternalError("Could not create extension class loader", var10);    }    try {        this.loader = Launcher.AppClassLoader.getAppClassLoader(var1);    } catch (IOException var9) {        throw new InternalError("Could not create application class loader", var9);    }    ...}復(fù)制代碼

到這里謎團(tuán)全部解開了:

在創(chuàng)建ClassLoder時(shí),

  1. 可以指定一個(gè)ClassLoder作為其parent,也就是其父加載器。
  2. 若沒有指定的話,會(huì)使用getSystemClassLoader()方法的返回值(也就是Launcher類中的AppClassLoader)作為其parent。
  3. 通過getParent()方法可以獲取到這個(gè)父加載器。
defineClass()

能將class二進(jìn)制內(nèi)容轉(zhuǎn)換成Class對(duì)象,如果不符合要求的會(huì)拋出異常,例如ClassFormatError、NoClassDefFoundError。

在自定義ClassLoader時(shí),我們通常會(huì)先將特定的文件讀取成byte[]對(duì)象,再使用此方法,將其轉(zhuǎn)為class對(duì)象。

ClassLoader類---------/*** String name:表示預(yù)期的二進(jìn)制文件名稱,不知道的話,可以填null。* byte[] b:此class文件的二進(jìn)制數(shù)據(jù)* int off:class二進(jìn)制數(shù)據(jù)開始的位置* int len:class二進(jìn)制數(shù)據(jù)的總長(zhǎng)度*/protected final Class<?> defineClass(String name, byte[] b, int off, int len)    throws ClassFormatError{    return defineClass(name, b, off, len, null);}protected final Class<?> defineClass(String name, byte[] b, int off, int len, ProtectionDomain protectionDomain)    throws ClassFormatError{    protectionDomain = preDefineClass(name, protectionDomain);    String source = defineClassSourceLocation(protectionDomain);    Class<?> c = defineClass1(name, b, off, len, protectionDomain, source);    postDefineClass(c, protectionDomain);    return c;}復(fù)制代碼
findClass()

findClass()方法一般被loadClass()方法調(diào)用去加載指定名稱類。

ClassLoader類---------/*** String name:class文件的名稱*/protected Class<?> findClass(String name) throws ClassNotFoundException {    throw new ClassNotFoundException(name);} 復(fù)制代碼

通過源碼看到ClassLoader類中并沒有具體的邏輯,而是等待著其子類去實(shí)現(xiàn),通過上面的分析我們知道兩個(gè)系統(tǒng)類加載器ExtClassLoader和AppClassLoader都繼承自URLClassLoader,那就來看一下URLClassLoader中的具體代碼。

URLClassLoader類---------protected Class<?> findClass(final String name) throws ClassNotFoundException{    final Class<?> result;    try {        result = AccessController.doPrivileged(            new PrivilegedExceptionAction<Class<?>>() {                public Class<?> run() throws ClassNotFoundException {                    String path = name.replace('.', '/').concat(".class");                    Resource res = ucp.getResource(path, false);                    if (res != null) {                        try {                            return defineClass(name, res);                        } catch (IOException e) {                            throw new ClassNotFoundException(name, e);                        }                        ...    return result;}private Class<?> defineClass(String name, Resource res) throws IOException {    ...    URL url = res.getCodeSourceURL();    ...    java.nio.ByteBuffer bb = res.getByteBuffer();    if (bb != null) {        ...        return defineClass(name, bb, cs);    } else {        byte[] b = res.getBytes();        ...        return defineClass(name, b, 0, b.length, cs);    }}復(fù)制代碼

可以看到其對(duì)傳入的name進(jìn)行處理后,就調(diào)用了defineClass(name, res);在這個(gè)方法里主要是通過res資源和url,加載出相應(yīng)格式的文件,最終還是通過ClassLoader的defineClass方法加載出具體的類。

loadClass()

上節(jié)說到findClass()一般是在loadClass()中調(diào)用,那loadClass()是什么呢? 其實(shí)loadClass()就是雙親委托機(jī)制的具體實(shí)現(xiàn),所以在我們先介紹下雙親委托機(jī)制后,再來分析loadClass()。

3 雙親委托機(jī)制介紹

3.1 圖解雙親委托機(jī)制

先簡(jiǎn)單介紹下雙親委托機(jī)制: 類加載器查找Class(也就是在loadClass時(shí))所采用的是雙親委托模式,所謂雙親委托模式就是

  1. 首先判斷該Class是否已經(jīng)加載
  2. 如果沒有則不是自身去查找而是委托給父加載器進(jìn)行查找,這樣依次的進(jìn)行遞歸,直到委托到最頂層的Bootstrap ClassLoader
  3. 如果Bootstrap ClassLoader找到了該Class,就會(huì)直接返回
  4. 如果沒找到,則繼續(xù)依次向下查找,如果還沒找到則最后會(huì)交由自身去查找


(圖片來自http://liuwangshu.cn/application/classloader/1-java-classloader-.html)


  • 其中紅色的箭頭代表向上委托的方向,如果當(dāng)前的類加載器沒有從緩存中找到這個(gè)class對(duì)象,就會(huì)請(qǐng)求父加載器進(jìn)行操作。直到Bootstrap ClassLoader。
  • 而黑色的箭頭代表的是查找方向,若Bootstrap ClassLoader可以從%JAVA_HOME%/jre/lib目錄或者-Xbootclasspath指定目錄查找到,就直接返回該對(duì)象,否則就讓ExtClassLoader去查找。
  • ExtClassLoader就會(huì)從JAVA_HOME/jre/lib/ext或者-Djava.ext.dir指定位置中查找,找不到時(shí)就交給AppClassLoader,AppClassLoader就從當(dāng)前工程的bin目錄下查找
  • 若還是找不到的話,就由我們自定義的CustomClassLoader查找,具體查找的結(jié)果,就要看我們?cè)趺磳?shí)現(xiàn)自定義ClassLoader的findClass方法了。

3.2 源碼分析雙親委托機(jī)制

接下來我們看看雙親委托機(jī)制在源碼中是如何體現(xiàn)的。 先看loadClass的源碼:

ClassLoader類---------protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException{    synchronized (getClassLoadingLock(name)) {        //首先,根據(jù)name檢查類是否已經(jīng)加載,若已加載,會(huì)直接返回        Class<?> c = findLoadedClass(name);        if (c == null) {            long t0 = System.nanoTime();            try {                if (parent != null) {                    //若當(dāng)前類加載器有父加載器,則調(diào)用其父加載器的loadClass()                    c = parent.loadClass(name, false);                } else {                    //若當(dāng)前類加載器的parent為空,則調(diào)用findBootstrapClassOrNull()                    c = findBootstrapClassOrNull(name);                }            } catch (ClassNotFoundException e) {            }                    if (c == null) {                // 1.如果到這里c依然為空的話,表示一直到最頂層的父加載器也沒有找到已加載的c,那就會(huì)調(diào)用findClass進(jìn)行查找                // 2.在findClass的過程中,如果指定目錄下沒有,就會(huì)拋出異常ClassNotFoundException                // 3.拋出異常后,此層調(diào)用結(jié)束,接著其子加載器繼續(xù)進(jìn)行findClass操作                long t1 = System.nanoTime();                c = findClass(name);                sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);                sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);                sun.misc.PerfCounter.getFindClasses().increment();            }        }        if (resolve) {            resolveClass(c);        }        return c;    }}復(fù)制代碼

findBootstrapClassOrNull()方法:可以看到其對(duì)name進(jìn)行校驗(yàn)后,最終調(diào)用了一個(gè)native方法findBootstrapClass()。在findBootstrapClass()方法中最終會(huì)用Bootstrap Classloader來查找類。

ClassLoader類---------private Class<?> findBootstrapClassOrNull(String name){    if (!checkName(name)) return null;    return findBootstrapClass(name);}    private native Class<?> findBootstrapClass(String name);復(fù)制代碼

4 常見的問題

4.1 為什么使用雙親委托機(jī)制?

  1. 避免重復(fù)加載,如果已經(jīng)加載過一次Class,就不需要再次加載,而是先從緩存中直接讀取。
  2. 安全方面的考慮,如果不使用雙親委托模式,就可以自定義一個(gè)String類來替代系統(tǒng)的String類,這樣便會(huì)造成安全隱患,采用雙親委托模式會(huì)使得系統(tǒng)的String類在Java虛擬機(jī)啟動(dòng)時(shí)就被加載,也就無法自定義String類來替代系統(tǒng)的String類。

4.2 由不同的類加載器加載的類會(huì)被JVM當(dāng)成同一個(gè)類嗎?

不會(huì)。 在Java中,我們用包名+類名作為一個(gè)類的標(biāo)識(shí)。 但在JVM中,一個(gè)類用其包名+類名和一個(gè)ClassLoader的實(shí)例作為唯一標(biāo)識(shí),不同類加載器加載的類將被置于不同的命名空間.

通過一個(gè)demo來看,

  1. 用兩個(gè)自定義類加載器去加載一個(gè)自定義的類
  2. 然后獲取到的Class進(jìn)行java.lang.Object.equals(…)判斷。
public class Main {    public static void main(String[] args) {            ClassLoaderTest myClassLoader = new ClassLoaderTest("F:\\");        ClassLoaderTest myClassLoader2 = new ClassLoaderTest("F:\\");        try {            Class c = myClassLoader.loadClass("com.example.Hello");            Class c2 = myClassLoader.loadClass("com.example.Hello");            Class c3 = myClassLoader2.loadClass("com.example.Hello");            System.out.println(c.equals(c2)); //true            System.out.println(c.equals(c3)); //flase    }}復(fù)制代碼

輸出結(jié)果:

truefalse復(fù)制代碼

只有兩個(gè)類名一致并且被同一個(gè)類加載器加載的類,Java虛擬機(jī)才會(huì)認(rèn)為它們是同一個(gè)類。

上面demo中用到的自定義ClassLoader:

自定義的類加載器注意點(diǎn):1.覆寫findClass方法2.讓其可以根據(jù)name從我們指定的path中加載文件,也就是將文件正確轉(zhuǎn)為byte[]格式3.使用defineClass方法將byte[]數(shù)據(jù)轉(zhuǎn)為Class對(duì)象-------------public class ClassLoaderTest extends ClassLoader{    private String path;    public ClassLoaderTest(String path) {        this.path = path;    }    @Override    protected Class<?> findClass(String name) throws ClassNotFoundException {        Class clazz = null;        byte[] classData = classToBytes(name);        if (classData == null) {            throw new ClassNotFoundException();        } else {            clazz= defineClass(name, classData, 0, classData.length);        }        return clazz;    }    private byte[] classToBytes(String name) {        String fileName = getFileName(name);        File file = new File(path,fileName);        InputStream in=null;        ByteArrayOutputStream out=null;        try {            in = new FileInputStream(file);            out = new ByteArrayOutputStream();            byte[] buffer = new byte[1024];            int length=0;            while ((length = in.read(buffer)) != -1) {                out.write(buffer, 0, length);            }            return out.toByteArray();        } catch (IOException e) {            e.printStackTrace();        }finally {            try {                if(in!=null) {                    in.close();                }            } catch (IOException e) {                e.printStackTrace();            }            try{                if(out!=null) {                    out.close();                }            }catch (IOException e){                e.printStackTrace();            }        }        return null;    }    private String getFileName(String name) {        int index = name.lastIndexOf('.');        if(index == -1){            return name+".class";        }else{            return name.substring(index+1)+".class";        }    }}復(fù)制代碼

結(jié)語(yǔ)

到此Java的類加載器以及雙親委托機(jī)制都講了個(gè)大概,如果文中有錯(cuò)誤的地方、或者有其他關(guān)于類加載器比較重要的內(nèi)容又沒有介紹到的,歡迎在評(píng)論區(qū)里留言,一起交流學(xué)習(xí)。


作者:某人Valar
鏈接:https://juejin.im/post/5e094d8df265da339772b7f6
來源:掘金
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。

(正文已結(jié)束)

推薦閱讀:買禮物

免責(zé)聲明及提醒:此文內(nèi)容為本網(wǎng)所轉(zhuǎn)載企業(yè)宣傳資訊,該相關(guān)信息僅為宣傳及傳遞更多信息之目的,不代表本網(wǎng)站觀點(diǎn),文章真實(shí)性請(qǐng)瀏覽者慎重核實(shí)!任何投資加盟均有風(fēng)險(xiǎn),提醒廣大民眾投資需謹(jǐn)慎!

網(wǎng)站簡(jiǎn)介 - 聯(lián)系我們 - 營(yíng)銷服務(wù) - 老版地圖 - 版權(quán)聲明 - 網(wǎng)站地圖
Copyright.2002-2019 寧夏資訊網(wǎng) 版權(quán)所有 本網(wǎng)拒絕一切非法行為 歡迎監(jiān)督舉報(bào) 如有錯(cuò)誤信息 歡迎糾正