0%

memcached过期删除

当某个值过期后,并没有从内存删除,因此,stats 统计时,curr_item 有其信息,当某个新值去占用他的位置时,当成空 chunk 来占用,当 get 值时,判断是否过期,如果过期,返回空并且清空,curr_item 就减少了.

这个过期,只是让用户看不到这个数据而已,并没有在过期的瞬间立即从内存删除,这个称为 lazy expiration,惰性失效,这样做的好处是节省了 cpu 时间和检测的成本

删除机制

memcached使用的是lru(least recently used 最近最少使用)删除机制

原理

当某个单元被请求时,维护一个计数器,通过计数器来判断最近谁最少被使用,就把谁踢出

即使某个 key 是设置的永久有效期,也一样会被踢出来,称为永久数据被踢现象

memcached内存管理

由于C语言直接 malloc、free 来向操作系统申请和释放内存时,在不断的申请和释放过程中,形成了一些很小的内存片断,无法再利用,这种空闲但无法利用内存的现象,称为内存的碎片化

如何解决内存碎片化

memcached 用 slab allocator 机制来管理内存有刺来解决内存碎片化问题

slab allocator 原理: 预告把内存划分成数个 slab class 仓库.(每个 slab class 大小 1M)各仓库,切分成不同尺寸的小块(chunk),需要存内容时,判断内容的大小,为其选取合理的仓库

阅读全文 »

基本命令

启动命令

1
memcached -m 64 -p 11211 -u nobody -vv

如果想要后台启动,则使用-d

1
/memcached -m 64 -p 11211 -u nobody -d
阅读全文 »

堆与虚拟机栈不同,堆的生命周期与JVM实例是一致的,一个JVM实例只存在一个堆内存,在JVM启动的时候就会被创建,其大小也就被确定了,所有的线程共享堆内存(不过还存在线程私有的缓冲区Thread Local Allocation Buffer,简称TLAB)

对于对象而言,对象的引用存在于栈帧中,这个引用指向了对象所在的堆中的位置

在方法执行结束后,堆中的对象不会被马上移除,会在垃圾回收时在进行移除

阅读全文 »

本地方法栈

java虚拟机栈用于管理java方法的调用,而本地方法栈则是用来管理本地方法的调用,本地方法栈也是线程私有的

本地方法

使用native进行修饰的方法,底层使用C/C++来进行实现

1
public static native Thread currentThread();

在本地方法栈中登记native方法,在执行引擎执行时加载本地方法

方法调用的指令说明

以一个简单地继承来说明一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
public interface Breathable {

void breath();
}

public class Parent implements Breathable{
public int field = 0;

public int getField(){
return field;
}

private void testPrivate(){
System.out.println("父类私有方法");
}

public Parent(int field){
this.field = field;
}

public static void testStatic(){

}

public final void testFinal(){

}

public void amountField(){
field+=5;
}

public Parent(){

}

@Override
public void breath() {
System.out.println("人当然会呼吸啦");
}
}

public class Child extends Parent {
public int field = 1;


@Override
public int getField(){
return field;
}

public void test(){

}

@Override
public void amountField(){
field+=5;
}

public static void main(String[] args) {
Parent p = new Child();
// 重写的实例方法 invokevirtual
p.amountField();
// 调用静态方法 invokestatic
p.testStatic();
// 调用父类的final方法 invokevirtual
p.testFinal();

Breathable breathable = new Child();
// 实现的接口方法 invokeinterface
breathable.breath();
//invokevirtual
System.out.println(p.getField());
System.out.println(p.field);

}
}
阅读全文 »

栈顶缓存技术

java虚拟机使用的是基于栈式架构的,而栈式架构使用的是零地址指令,指令更加紧凑,但是完成一项操作需要更多的入栈出栈指令,即需要更多的指令分派次数和内存读写次数,而频繁的读写内存肯定会影响执行速度,所以HotSpot JVM中有一个栈顶缓存技术,将栈顶元素全部存储在物理CPU寄存器中,以此降低对内存的读写次数,提升执行引擎的执行效率

虚拟机栈

虚拟机栈(Java Virtual Machine Stack),每个线程在创建时都会创建一个虚拟机栈,内部保存一个个的栈帧(Stack Frame),对应着一次次的方法调用,生命周期与线程一致,主要用来管理java程序的运行,保存方法的局部变量、部分结果,并参与方法的调用和返回

虚拟机栈的访问速度是很快的,仅次于程序计数器,JVM对于虚拟机栈的操作只有两个入栈(方法执行)和出栈(方法结束)

虚拟机栈并不存在垃圾回收

阅读全文 »

程序计数器

程序计数器(Program Counter Register)是用来存储指向下一条指令的地址,也就是即将要执行的指令代码,有执行引擎来读取下一条指令,每个线程都有自己的一个程序计数器,程序计数器的生命周期与线程的一致,在任何时间同一个线程只会执行一个方法,也就是当前方法,程序计数器会存储当前线程正在执行方法的JVM指令地址,如果执行的是native方法,在指令地址是undefined

程序计数器是JVM规范中唯一一个不会出现OOM的区域,且也不存在垃圾回收

阅读全文 »

类加载器

类加载器子系统负责从文件系统或者网络中加载class文件,class文件在文件开头有特定的文件标识,将class字节码文件在类装载器子系统(Class Loader SubSystem)中有三个阶段

  • 1.加载 到内存中需要用到类加载器
  • 2.链接 链接中包含 验证、准备和解析
  • 3.初始化

加载阶段

ClassLoader只负责class文件的加载,是否可以运行是由Execution Engine决定,加载的类信息存放于一块称为方法区的内存空间。除了类的信息外,方法区中还会存放运行时常量池信息(包括字符串字面量和数字常量,是class文件中常量池部分的内存映射)

阅读全文 »