JVM 深入理解
Java

前言

JVM版本信息

问题:请你谈谈你认识几种 JVM?(3种)

  • SUN 公司 HotSpot (默认,掌握这个jvm即可)
  • BEA 公司 JRockit
  • IBM 公司 J9VM

问题:jvm除了Service模式是否有Client模式?他们有什么区别?如何修改?(了解即可)

  • Server模式启动时,速度较慢,但是一旦运行起来后,性能将会有很大的提升(64位系统默认)

  • Client模式启动时,启动较快,占用内存少,针对客户端进行优化(32位系统默认,一般用不到)

  • 在路径JAVA_HOME/jre/lib/amd64/jvm.cfg 修改-server和-client的配置即可完成更改。

    修改模式

问题:jvm有几种mode?如何修改?(了解即可)

  • mixed mode(默认):混合模式执行,编译+执行。 -Xmixed
  • interpreted mode :解释模式执行。 -Xint
  • compiled mode :编译模式执行。 -Xcomp

切换mode

JVM的位置

jvm位置

  • 是java程序跨平台,不是jvm跨平台,jvm将java代码编译成不同操作系统能执行的.class字节码。

JVM体系架构

JVM体系架构图

ClassLoader

ClassLoader的层级

ClassLoader的层级

  • 官方提供了3种ClassLoader

BootStrap ClassLoader

称为启动类加载器,处于加载器的最顶层,负责加载rt.jar、resources.jar、charsets.jar等,由于是C写的所以java程序触及不到。

public class JvmDemo {
public static void main(String[] args) {
System.out.println(System.getProperty("sun.boot.class.path"));
//所有对象的祖宗object是第一个被加载的类,被BootStrap ClassLoader加载,但是我们访问不到
System.out.println(Object.class.getClassLoader());
}
}

输出结果

Ext ClassLoader

称为扩展类加载器,父类是BootStrap ClassLoader,负责加载Java的扩展类库,Java 虚拟机会提供一个扩展库目录,该类加载器在此目录里面查找并加载 Java 类。默认加载JAVA_HOME/jre/lib/ext/目下的所有jar。

public class JvmDemo {
public static void main(String[] args) {
System.out.println(System.getProperty("java.ext.dirs"));
}
}

执行结果

App ClassLoader

称为应用程序加载器,父类是Ext ClassLoader,负责加载我们自定义的类,是我们接触最多的加载器,加载classpath下面的类。

public class JvmDemo {
public static void main(String[] args) {
System.out.println(JvmDemo.class.getClassLoader());
}
}

执行结果

双亲委派机制

双亲委派机制 可以保护java的核心类不会被自己定义的类所替代

一层一层的让父类去加载,如果顶层的加载器不能加载,然后再向下类推,直到某个类加载器覆盖到了为止。

类加载的过程

  • 当一个类被第一次加载的时候,jvm会通过类加载器将.class文件载入内存当中(方法区),并将这个类创建一个全局唯一的Class对象作为这个类对象的模板。
  1. 加载.class文件

  2. 连接

    1. 验证:验证.class文件是否正确
    2. 准备:给静态变量分配内存空间并赋予初始值(基本数据类型:0、false,引用类型:null)
    3. 解析:将类中的符号引用替换为为真实引用
    在把java编译为class文件的时候,虚拟机并不知道所引用的地址;助记符:符号引用!
    转为真正的直接引用,找到对应的直接地址!
  3. 静态变量赋予正确的值

静态块

当类被加载时,会执行的代码块:static{},从基类开始从上至下加载。

package vc.coding.jvm;

public class Demo02 {
public static void main(String[] args) {
System.out.println(MyChild1.str2);
// 运行的结果
/**
* MyParent1 static
* MyChild1 static
* hello,str2
*/
}
}

class MyParent1{
public static String str = "hello,world";
static {
System.out.println("MyParent1 static");
}
}

class MyChild1 extends MyParent1{
public static String str2 = "hello,str2";
static {
System.out.println("MyChild1 static");
}
}

静态常量

当一个常量的值如果编译期间可以确定的,那这个值就会被加载到调用者类的常量池中!

package vc.coding.jvm;

import java.util.UUID;

/**
* @author HeTongHao
* @since 2020/3/11 14:25
*/
public class JvmDemo {
public static void main(String[] args) {
System.out.println(StaticBlock.str);
}
/**
* final 常量在编译阶段的时候 常量池;
* 调用 str 的过程将常量放到了 JvmDemo 的常量池中,所以静态块没有被执行
* 调用 str1 的过程加载了StaticBlock类并且执行了UUID.randomUUID().toString() JvmDemo 的常量池 * 中,所以静态块会被执行
*/
}

class StaticBlock {
/**
* 加载类的时候有确定的值
*/
public static final String str = "123";
/**
* 加载类的时候未确定的值
*/
public static final String str1 = UUID.randomUUID().toString();

static {
// 这句话会输出吗?
System.out.println("StaticBlock static");
}
}

Native方法

  • JNI : Java Native Interface (Java 本地方法接口)
  • 凡是带native关键字的方法都是本地方法
  • java触及不到的功能,就会调用C或C++的本地方法库,比如说java不能创建线程:
  • 1995年,java 还未立足所以必须可以去调用 c、c++的库,所以说Java就在内存中专门开辟了一块区域标记为 native 方法。
public class Test {
public static void main(String[] args) {
// 底层调用的是 private native void start0();
new Thread().start();
}
}

程序计数器

每个线程都有一个程序计数器,是线程私有的。

程序计数器就是一块十分小的内存空间;几乎可以不计

作用: 当前字节码执行的行号指示器

程序计数器

分支、循环、跳转、异常处理!都需要依赖于程序计数器来完成!

bipush 将 int、float、String、常量值推送值栈顶

istore 将一个数值从操作数栈存储到局部变量表

iadd

imul

栈 Stack

什么是栈?

  • 对比队列来说

    队列是吃多了拉 = 先进先出 = FIFO(First Input First OutPut)

    栈是喝多了吐 = 后进先出 = LIFO (Last Input First OutPut)

队列与栈

  • 栈是线程私有的(每个线程都有自己的栈)
  • 栈是掌管程序运行的,毎执行一个命令就是往栈中压一层,直到最后上一层执行完毕之后就弹出,栈空了线程就Over了。压栈

  • 存储一些基本类型的值、对象的引用(引用指向堆内存)、方法等…

    问:为什么java的方法传递是值传递而不是引用传递?

    答:因为实参传递到方法形参的过程,就是把栈中对象的引用值(也可以理解为堆的地址)传递过去,形参同样会开辟栈空间存储这个引用。

引用指向堆内存

  • 栈存取速度比堆快!仅次于cpu寄存器。

StackOverFlow

public class Demo01 {
public static void main(String[] args) {
a();
}
// main a a a a a a a a a a a 满
// Exception in thread "main" java.lang.StackOverflowError
private static void a() {
a();
}
}
  • 栈是一定不会存在垃圾回收的问题的,只要线程一旦结束,栈就Over了,与线程的生命周期一致。

Stack 原理

  • java栈的组成元素 :栈帧
  • 每个栈帧存储着父、子栈帧的引用、方法引用、参数等…

栈帧

方法区

  • 因为物理上不在堆中而逻辑上可以归为堆中(下面👇堆会提到),所以又称:非堆区(Non-Heap space)

  • Method Area 方法区 是 Java虚拟机规范中定义的运行数据区域之一,和堆(heap)一样可以在线程之间共享!

JDK1.7之前

永久代:用于存储一些虚拟机加载类信息,常量,字符串、静态变量等等。。这些东西都会放到永久代中;

永久代大小空间是有限的:如果满了 OutOfMemoryError:PermGen

JDK1.8之后

HotSpot jvm 中彻底将永久代移除,新增了 Meta Spaces (元空间)

元空间就是方法区在 HotSpot jvm 的实现;

方法区主要就是来存:类信息,常量,字符串、静态变量、符号引用、方法代码。。。

元空间和永久代最大的区别:元空间并不在Java虚拟机中,使用的是本地内存!

调整元空间大小:-XX:MetasapceSize10m

堆 Heap

什么是堆?

  • 一个JVM实例只有一个堆,可供所有线程共享数据,堆的大小是可以调节的。

  • 可以存储的内容:对象实例、类、方法、常量。

  • 分为三个部分:

    • 新生区 Young (Eden-from-to)
    • 养老区 Old Tenure
    • 方法区(1.7之前:永久区 Perm,之后:元空间 Meta Space)(逻辑上)
  • GC垃圾回收主要发生在新生区与养老区中,又分为普通GC和Full GC,如果堆满了,则会报出OOM异常(OutOfMemoryError)。

调整堆的大小

  • -Xmx:最大堆大小 (默认为系统内存的1/4)

  • -Xms:初始堆大小 (默认为系统内存的1/64)

  • -Xmn: 年轻代大小 (默认为堆的1/3)

新生区

  • 新生区是一个对象诞生、成长、消亡的地方。

  • 新生区的细分:Eden、s0与s1区(from to),所有的对象Eden被new出来,慢慢当Eden满了,程序还需要创建对象的时候,会触发一次轻量级的GC,清理完后将活下来的对象放入幸存者区(也就是s0与s1),毎执行一次轻GC就会将活着的对象在s0与s1中进行复制、交换、销毁(下面👇GC会详细解释)。

  • 99%的对象在新生区都是临时对象,在这里创建也在这里消亡。

养老区

  • 新生区中清理了很多次之后,如果有一些特别顽强的对象经历了15次垃圾回收(默认也是最大值15,可调参)!则送入养老区!

  • 如果运行了很久之后,养老区也满了,就会触发Full GC。

  • 如果养老区都清理不动了的话,则会出现OOM异常。

方法区(永久区、元空间)

  • 存放类信息、方法、常量。

  • 几乎不会被垃圾回收。

    • 常量回收条件:当没有对象引用一个常量的时候,该常量即可以被回收。

    • 对象回收条件:1.该类的实例都被回收。 2.加载该类的classLoader已经被回收 3.该类不能通过反射访问到其方法,而且该类的java.lang.class没有被引用 当满足这3个条件时,可以被回收。

  • 方法区和堆一样,是共享的区域,是JVM 规范中的一个逻辑的部分,别名:非堆。

JDK1.6之前:有永久代、常量池在方法区;

JDK1.7:有永久代、但是尝试去永久代,常量池在堆中;

JDK1.8之后:永久代没有了,取而代之的是元空间:常量池在元空间中;

标配参数、-X、-XX参数

  • JVM只有三种参数类型:标配参数、X参数、XX参数。

标配参数

  • - 开头的为标配参数

  • 在各种版本之间都很稳定,很少有变化

X参数

  • -X 开头的为标配参数

XX参数

  • -XX 开头的为标配参数
  • 公式:
    • Boolean类型
      • -XX:+开头代表开启某个功能,例如:-XX:+PrintGCDetails。
      • -XX:-开头代表关闭某个功能,例如:-XX:-PrintGCDetails。
    • Key=Value类型
      • -XX:key=value,例如:-XX:InitialHeapSize=268435456。

常用JVM调优参数整理

标配参数

参数 描述
-verbose:class 输出jvm载入类的相关信息,当jvm报告说找不到类或者类冲突时可此进行诊断。
-verbose:gc 输出每次GC的相关情况。
-verbose:jni 输出native方法调用的相关情况,一般用于诊断jni调用错误信息。

-X参数

参数 描述
-Xint 解释执行
-XComp 第一次使用就编译成本地的代码
-Xmixed 混合模式(Java默认)
-Xprof 跟踪正运行的程序,并将跟踪数据在标准输出输出;适合于开发环境调试。

-XX参数

参数 描述
-Xmx8m 最大堆内存8m (-XX:InitialHeapSize=8m缩写)
-Xms8m 初始堆内存8m (-XX:MaxHeapSize=8m缩写)
-Xmn200m 设置年轻代大小为200M。整个堆大小=年轻代大小 + 年老代大小 + 持久代大小。持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。(缩写语法糖)
-Xss128k 设置每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。更具应用的线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。(缩写语法糖)
-XX:+PrintGCDetails 打印GC详情
-XX:+HeapDumpOnOutOfMemoryError dump 内存溢出异常
-XX:MetaspaceSize=10m 元空间大小=10m
-XX:MaxMetaspaceSize=10m 最大元空间大小=10m
-XX:+TraceClassLoading 跟踪类加载
-XX:MaxTenuringThreshold = 15 进入老年区的存活阈值
-XX:NewRatio=2 设置年轻代与老年代的占比:NewRatio = 2 新生代1,老年代是2,默认新生代整个堆的 1/3;NewRatio = 4 新生代1,老年代+是4,默认新生代整个堆的 1/5;

Java程序监控、Dump内存快照

  • -XX:+HeapDumpOnOutOfMemoryError可以在内存溢出时,dump内存快照
  • -XX:HeapDumpPath=目录+产生的时间.hprof设置内存快照生成地址
  • 在java程序运行的时候,想测试运行的情况!可以使用一些工具来查看:

Jconsole

  • jps命令:查看当前运行java进程jps命令

  • jconsole 进程号:查看java进程当前运行状况:

    jconsole

    jconsole控制台

IDEA(Jprofiler插件)

  • Jprofiler是一个强大的java程序监控软件,功能十分丰富!

  • Jprofiler官网下载安装: https://www.ej-technologies.com/products/jprofiler/overview.html

  • 在IDEA 中绑定 JProfiler,则可在idea以Jprofiler监控的方式启动:IDEA 中绑定 JProfiler

    以Jprofiler启动

    Jprofiler监控

Arthas

  • 我的另一篇博客有详细解释: Arthas - java服务监控神器

GC

GC就是java中的垃圾回机制,一直在追求更快且高效的道路中。

随着应用程序所应对的业务越来越庞大、复杂,用户越来越多,没有GC就不能保证应用程序正常进行。而经常造成STW的GC又跟不上实际的需求,所以才会不断地尝试对GC进行优化

GC的作用域

GC作用域

  • 新生代:GC频繁区域!
  • 老年代:GC次数较少!
  • 方法区:GC次数极少!

一个对象的诞生、成长、消亡

一个对象的诞生、成长、消亡

  • GC分为两个类型:
    • 普通垃圾回收:只针对新生代!「 GC
    • 完全垃圾回收:主要针对老年代,偶尔伴随新生代或方法区!「 Full GC

GC四大算法

复制算法

  • 新生代中就是使用复制算法!
  1. 一般普通GC 之后,差不多Eden几乎都是空的了!

复制算法图解

  1. 每次存活的对象,都会被从 from 区和 Eden区复制到 to区,from 和 to 会发生一次交换;记住一个点就好,谁空谁是to,每当幸存一次,就会导致这个对象的年龄+1;如果这个年龄值大于15(默认也是最大值15,可调参),就会进入养老区!
  • 优点:没有标记的过程、只用扫描一次,效率高!没有内存碎片!
  • 缺点:需要浪费一倍的空间

标记清除算法

  • 老年代一般用的算法,并且和后面的压缩算法一起使用!

标记清除算法

优点:不需要额外的空间!

缺点:两次扫描、耗时比较严重,并且会产生内存碎片,内存不连续!(如果再来存东西会多判断这个地址是否存的下)

标记清除压缩算法

  • 就是在标记清除算法后面加了一次压缩,去内存碎片!

内存压缩

优点:不需要额外的空间!无内存碎片!

缺点:耗时同样比较严重!

在我们这个要使用算法的空间中,假设这个空间中对象较少,不经常发生GC,那么可以考虑使用这个算法!

小总结

  • 内存效率:复制算法 > 标记清除算法 > 标记压清除缩算法(时间复杂度)

  • 内存整齐度:复制算法=标记清除压缩算法>标记清除算法

  • 内存利用率:标记清除压缩算法 = 标记清除算法 > 复制算法

效率上来说复制算法最好,但是浪费空间较多!为了兼顾所有指标,标记清除压缩算法比较平滑,但是也不太完美!

难道没有一种最优的算法吗?

答案:没有!没有最好的只有最合适的!—–>分代收集算法:不同的区域使用不同的算法!

分代收集算法

新生代:相对于老年代,存活率较低、GC次数较多、99%的对象在这里被清理、区域小!推荐使用:复制算法!

老年代:相对于新生代,存活率高、GC次数较少、区域比较大! 推荐使用:标记清除压缩算法!

JVM 如何确定垃圾?

什么是垃圾:简单来说,就是不再被引用的对象!

Person person = new Person();
Person person = null;

引用计数法(了解即可)

  • JVM一般不采用这种方式,现在一般使用可达性算法,GC Root。
  • 引用计数法就是每个对象有一个引用计数器,被几个对象所引用count就是几,如果为0,则这个对象可以被清理。

引用计数法

如此可知每次发生GC时,上图A对象count=0,所以会被清理,而其他对象则不会被清理,这里有一个严重的问题,比如C与D对象是互相引用的关系,这两个对象可能永远无法被清理。

  • 缺点:
    • 引用计数器维护麻烦!
    • 循环引用无法解决!

可达性算法

  • 一切都是从 GC Root 这个对象开始遍历的,只要在GC Root的引用链中就不是垃圾!

可达性算法

什么是GC Root(4种)

  1. 虚拟机栈中引用的对象。

  2. 在类中静态属性引用的对象。

  3. 在方法区中的常量。

  4. 本地方法栈中Native方法引用的对象(JNI了解即可)。

    public class GCRoots{
    // private static GCRoots2 t2; // GC root;
    // private static final GCRoots3 t3 = new GCRoots3(); // GC root;
    public static void m1(){
    GCRoots g1 = new GCRoots(); //GC root;
    System.gc();
    }

    public static void main(String[] args){
    m1();
    }
    }

不同的垃圾收集器

  • 垃圾收集器工作方式分为四大类:串行、并发、并行、G1。

STW:Stop the World:代表JVM准备GC时,所有的线程都停止!

串行收集器

  • 单线程收集,会STW

串行收集器

并发收集器

  • 多线程工作,也会STW
  • 并发:一个cpu同时处理多个任务

并发收集器

并行收集器

  • 在回收垃圾的同时,其它线程可以执行,并行处理,但是如果是单核CPU,只能交替执行!
  • 并行:多个cpu同时处理多个任务

并行收集器

G1收集器 (待深入研究)

  • G1(Garbage-First)收集器,面向服务器端的应用的收集器;
  • 将堆内存分割成不同的区域,然后并发的对其进行垃圾回收。
  • -XX:MaxGCPauseMillis=100 调整最大的GC停顿时间单位:毫秒,JVM尽可能的保证停顿小于这个时间!

G1收集器

G1的优点:

  1. 没有内存碎片。
  2. 可以精准控制垃圾回收时间。

七种垃圾收集器

JDK7/8中,HotSpot虚拟机所有收集器及组合(连线),如下图:

七大垃圾收集器组合

  • 图中一共有7中收集器

    Serial、ParNew、Parallel Scavenge、Serial Old、Parallel Old、CMS、G1。

  • 它们每个收集器都有自己负责的区域:

    • 新生代收集器:Serial、ParNew(串行的多线程版本)、Parallel Scavengez
    • 老年代收集器:Serial Old、Parallel Old、CMS
    • 整堆收集器:G1

哪个是默认的垃圾收集器?

  • 垃圾收集器一直在更新换代,到了jdk8默认的是Parallel Scavenge + Serial Old,而到了jdk9则默认为G1收集器了。

查看默认的垃圾收集器

java -XX:+PrintCommandLineFlags -version

查看默认垃圾收集器

如何选择/设置垃圾回收器

  • 设置了任何一个新生代收集器默认会匹配一个对应的老年代收集器
  1. 单CPU,单机程序,内存小。

    -XX:+UseSerialGC

  2. 多CPU,大吞吐量,后台计算!

    -XX:+UseParNewGC

  3. 多CPU,但是不希望有时间停顿,快速响应!

    XX:+UseParallelGC-XX:+UseG1GC

摘自 《深入理解 Java 虚拟机》第二版 P90

参数 描述
UseSerialGC 虚拟机运行在Client模式下的默认值,打开此开关后,使用 Serial + Serial Old 的收集器组合进行内存回收
UseParNewGC 打开此开关后,使用 ParNew + Serial Old 的收集器组合进行内存回收
UseConcMarkSweepGC 使用 ParNew + CMS + Serial Old 的收集器组合进行内存回收。Serial Old 收集器将作为 CMS 收集器出现 Concurrent Mode Failure 失败后的后备收集器使用
UseParallelGC 虚拟机运行在 Server 模式下的默认值, 使用 Parallel Scavenge + Serial Old(PS MarkSweep) 的收集器组合进行内存回收
UseParallelOleGC 使用 Parallel Scavenge + Parallel Old 的收集器组合进行回收内存
ServivorRatio 新生代中 Eden 区域与 Survivor 区域的容量比值,默认为8,代表 Eden : Survivor=8 : 1
PretenureSizeThreshold 直接晋升老年代的对象大小,设置这个参数后,大于这个参数的对象将直接在老年代分配
MaxTenuringThreshold 晋升到老年代的对象年龄。每个对象在坚持过一次 Minor GC 之后,年龄旧增加1,当超过这个参数值就进入老年代
UseAdaptiveSizePolicy 动态调整 Java 堆中各个区域的大小以及进入老年代的年龄
HandlePromotionFailiure 是否允许分配担保失败,即老年代的剩余空间不足以应付新生代的整个 Eden 和 Survivor 区的所有对象都存活的极端情况
ParallelGCThreads 设置并行 GC 时进行内存回收的线程数
GCTimeRatio GC 时间占总时间的比率,默认值为99,即允许1%的 GC 时间。仅在使用 Parallel Scavenge 收集时生效
MaxGCPauseMillis 设置 GC 的最大停顿时间。仅在使用 Parallel Scavenge 收集器时生效
CMSInitiatingOccupancyFraction 设置 CMS 收集器在老年代空间被使用多少后触发垃圾收集。默认值68%,尽在使用CMS 收集器时生效
UseCMSCompactAtFullCollection 设置 CMS 收集器在完成垃圾收集后是否要进行一次内存碎片整理。仅在使用 CMS 收集器时生效
CMSFullGCsBeforeCompaction 设置 CMS 收集器在进行若干次垃圾收集后再启动一次内存碎片整理。仅在使用 CMS 收集器时生效
UseG1GC 使用 G1 (Garbage First) 垃圾收集器
文章作者: 何同昊
文章链接: http://hetonghao.cn/2020/03/jvm/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 何同昊 Blog!
支付宝超级火箭🚀
微信超级火箭🚀

深圳SEO优化公司泰安高端网站设计多少钱沙井网站开发价格大鹏网站定制价格安康百度网站优化排名价格怒江关键词按天计费多少钱哈尔滨关键词按天扣费公司襄阳品牌网站设计哪家好崇左百搜标王哪家好钦州建设网站推荐邯郸网站推广工具多少钱日照网站制作红河建站推荐威海网站搭建公司芜湖网站搭建价格三明外贸网站设计哪家好绥化外贸网站制作公司景德镇SEO按天扣费哪家好惠州网站搜索优化多少钱三明网站改版报价山南高端网站设计报价枣庄营销型网站建设哪家好临夏SEO按天计费多少钱德宏网站建设价格泉州网站建设设计报价石家庄推广网站多少钱枣庄建设网站马鞍山百度关键词包年推广宝安建站公司海东seo网站推广价格韶关品牌网站设计多少钱歼20紧急升空逼退外机英媒称团队夜以继日筹划王妃复出草木蔓发 春山在望成都发生巨响 当地回应60岁老人炒菠菜未焯水致肾病恶化男子涉嫌走私被判11年却一天牢没坐劳斯莱斯右转逼停直行车网传落水者说“没让你救”系谣言广东通报13岁男孩性侵女童不予立案贵州小伙回应在美国卖三蹦子火了淀粉肠小王子日销售额涨超10倍有个姐真把千机伞做出来了近3万元金手镯仅含足金十克呼北高速交通事故已致14人死亡杨洋拄拐现身医院国产伟哥去年销售近13亿男子给前妻转账 现任妻子起诉要回新基金只募集到26元还是员工自购男孩疑遭霸凌 家长讨说法被踢出群充个话费竟沦为间接洗钱工具新的一天从800个哈欠开始单亲妈妈陷入热恋 14岁儿子报警#春分立蛋大挑战#中国投资客涌入日本东京买房两大学生合买彩票中奖一人不认账新加坡主帅:唯一目标击败中国队月嫂回应掌掴婴儿是在赶虫子19岁小伙救下5人后溺亡 多方发声清明节放假3天调休1天张家界的山上“长”满了韩国人?开封王婆为何火了主播靠辱骂母亲走红被批捕封号代拍被何赛飞拿着魔杖追着打阿根廷将发行1万与2万面值的纸币库克现身上海为江西彩礼“减负”的“试婚人”因自嘲式简历走红的教授更新简介殡仪馆花卉高于市场价3倍还重复用网友称在豆瓣酱里吃出老鼠头315晚会后胖东来又人满为患了网友建议重庆地铁不准乘客携带菜筐特朗普谈“凯特王妃P图照”罗斯否认插足凯特王妃婚姻青海通报栏杆断裂小学生跌落住进ICU恒大被罚41.75亿到底怎么缴湖南一县政协主席疑涉刑案被控制茶百道就改标签日期致歉王树国3次鞠躬告别西交大师生张立群任西安交通大学校长杨倩无缘巴黎奥运

深圳SEO优化公司 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化