0%

源码分析之上下文构建

先从最简单的上下文初始化来开始说起

1
ApplicationContext context = new ClassPathXmlApplicationContext("spring-lifecycle.xml");

一个简单地创建ApplicationContext实例的方法,spring会做什么事呢?

1
2
3
4
5
6
7
8
9
10
11
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {

super(parent);
// 为上下文设置配置文件的位置
setConfigLocations(configLocations);
if (refresh) {
// 刷新上下文
refresh();
}
}

spring在初始化上下文的最重要的方法就是这个refresh()方法了

阅读全文 »

spark streaming容错

为了spark streaming可以有强大的容错保障,必须设置检查点,检查点机制主要有两个目的

  • 控制发生失败时需要重算的状态数
  • 提供驱动器程序容错

驱动器程序容错

阅读全文 »

执行引擎

执行引擎也是JVM中的一个重要组成部分,JVM主要任务是装载字节码,但是字节码并不能直接运行在操作系统上,所以还需要一个可以将字节码翻译成操作系统认识的机器指令的组件,而这个组件就是执行引擎

工作过程

当执行完一条指令后,程序计数器就会更新下一条需要被执行的指令地址,在方法执行过程中,执行引擎也可能会通过存储在局部变量表中的对象引用准确定位到存储在java堆区中的对象实例信息以及通过对象头中的元数据指针定位到目标对象的类型信息

执行引擎流程
阅读全文 »

对象在JVM中的生活

在java中万事万物皆对象,而java是在JVM中进行运行的,那么对象在JVM中是如何运作的呢?我们既要知道对象是怎么来的,也要知道对象时怎么没的

先来看一下我们看到的是如何创建对象的

创建对象的几种方式

有以下几种方式

  • 使用new进行实例化
1
TestObject testObject = new TestObject();
  • 使用Class的newInstance()

主要该方式调用的是无参的构造器,且必须是public的

1
TestObject testObject1 = TestObject.class.newInstance();
阅读全文 »

字符串常量

String是不可变的字符序列,体现为以下三种情况

  • 当字符串重新赋值时,需要重写指定内存区域赋值,不能使用原有的value进行赋值
  • 当对现有字符串进行连接操作时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值
  • 当调用String的replace方法修改指定字符串时,也需要重新指定内存区域赋值,不能使用原有value进行赋值

通过字面量的方式给一个字符串赋值,字符串值声明在了字符串常量池中,字符串常量池中不会存储相同的字符串的

1
String name = "张三";

字符串常量池的底层结构

阅读全文 »

javap命令

1
2
#javap的语法
javap [选项] class文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#javap 的命令选项
-version 版本信息
-v -verbose 输出附加信息
-l 输出行号和本地变量表
-public 仅显示公共类和成员
-protected 显示受保护的/公共类和成员
-package 显示程序包/受保护的/公共类
和成员 (默认)
-p -private 显示所有类和成员
-c 对代码进行反汇编
-s 输出内部类型签名
-sysinfo 显示正在处理的类的
系统信息 (路径, 大小, 日期, MD5 散列)
-constants 显示最终常量
-classpath <path> 指定查找用户类文件的位置
-cp <path> 指定查找用户类文件的位置
-bootclasspath <path> 覆盖引导类文件的位置

OOM问题解决

  • 先要找到问题是出在堆空间还是方法区,根据爆出来的异常信息就知道了,方法区爆出来的是java.lang.OutOfMemoryError:Metaspace
  • 然后通过分析工具来对dump出来的快照进行分析,来看是内存泄漏还是内存溢出
  • 如果是内存泄漏,使用工具查看内存泄漏对象到GC Roots的引用链,找到泄漏对象是通过怎样的路径与GC Roots相关联并导致垃圾回收器无法自动回收,定位出泄漏代码的位置
  • 如果不是内存泄漏,那就说明内存中的对象都必须存活着,就只能适当的调虚拟机参数了(-Xms和-Xmx)
  • 在检查一下是不是有某些对象的生命周期过长(不必要的静态调整为非静态,方法外定义的看看可不可以移到方法内),尝试减少程序运行期的内存消耗

字节码文件

字节码文件中包含的内容有包含类的版本信息、字段、方法以及接口等描述信息外,还有常量池表(Constant Pool Table),包括各种字面量和对类型、域(Field)和方法的符号引用

使用springSession完成分布式session

分布式session可以使用spring session来进行实现,由于HttpRequest的Wrapper功能,许多HttpRequest中的方法都可以进行替换来进行自定义的重写,所以可以将getSession方法重写掉,然后进行自定义的session存储和处理,当然了,你能想到的,一般都是早就有人已经实现了,就不重复造轮子了

spring session已经实现出了上述功能,只需要进行配置就可以实现啦

这里演示的是将session存储在redis中,所需要的依赖

1
2
3
4
5
6
7
8
9
10
11
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
<version>1.3.5.RELEASE</version>
</dependency>

<dependency>
<groupId>biz.paluch.redis</groupId>
<artifactId>lettuce</artifactId>
<version>3.4.2.Final</version>
</dependency>
阅读全文 »

方法区

方法区在逻辑上虽然属于堆的一部分,但是简单的实现上可能不会选择去进行垃圾回收或者进行压缩,在Hotspot中为了区分方法区和堆,方法区又被称为非堆,所以**方法区可以看做是独立于堆的一块内存空间**

方法区的生命周期与JVM实例也是一致的,在JVM启动的时候就会被创建,也是各个线程共享的区域,其存储的是类的信息,所以方法区的大小决定了系统可以保存多少个类,如果系统定义的类过多,方法区就会溢出,从而出现OOM

jdk7及之前报的是java.lang.OutOfMemoryError:PermGen space,jdk8报的是java.lang.OutOfMemoryError:Metaspace

元空间

阅读全文 »