MySQL -- 基础架构
查询语句1mysql> select * from T where ID=10; 基本架构 大体上,MySQL可以分为Server层和存储引擎层 Server层包括连接器、查询缓存、分析器、优化器和执行器等 涵盖MySQL的大多数核心服务功能,以及所有的内置函数 所有的跨存储引擎的功能都在这一层实现,例如存储过程、触发器和视图等 存储引擎层负责数据的存储和提取,架构模式为插件式 支持InnoDB、MyISAM和Memory等存储引擎 最常用为InnoDB(Since 5.5.5,默认) 连接器连接器负责跟客户端建立连接、获取权限、维持和管理连接,命令如下 1$ mysql -h$host -P$port -u$user -p 权限 mysql是客户端工具,用来与服务端建立连接 在完成TCP三次握手之后,连接器就要开始认证身份,即-u和-p 如果账号密码不对,客户端会收到Access denied for user的错误 如果账号密码认证通过,连接器会到权限表里查询拥有的权限 之后在这个连接里的权限判断,都依赖于此时读取的权限 因此即使用管理员账号对权限进行修改,也不会影响到...
JVM进阶 -- 浅谈Java Agent
Java Agent的运行方式 JVM并不会限制Java Agent的数量 可以在JVM参数中包含多个-javaagent参数 也可以远程attach多个Java Agent JVM会按照参数的顺序或者attach的顺序,逐个执行Java Agent JRebal/Btrace/arthas等工具都是基于Java Agent实现的 premain以JVM参数(-javaagent)的方式启动,在Java程序的main方法执行之前执行 MyAgent12345678package me.zhongmingmao;public class MyAgent { // JVM能识别的premain方法接收的是字符串类型的参数,并非类似main方法的字符串数组 public static void premain(String args) { System.out.println("premain"); }} manifest.txt12345678910# 写入两行数据,最后一行为空行$ ...
JVM进阶 -- 浅谈JNI
native方法123public class Object { public native int hashCode();} 当Java代码调用native方法时,JVM将通过JNI,调用至对应的C函数Object.hashCode()就是一个native方法,对应的C函数将计算对象的哈希值,并缓存在对象头、栈上锁记录(轻量级锁)或者对象监视锁(重量级锁,monitor)中,以确保该值在对象的生命周期之内不会变更 链接方式在调用native方法之前,JVM需要将该native方法链接至对应的C函数上 自动链接JVM自动查找符合默认命名规范的C函数,并且链接起来 Java代码12345678package me.zhongmingmao.advanced.jni;public class Foo { int i = 0xDEADBEEF; public static native void foo(); public native void bar(int i, long j); public native void bar(String ...
JVM进阶 -- MAT
概念Shallow Heap + Retained HeapShallow HeapShallow heap is the memory consumed by one object. An object needs 32 or 64 bits (depending on the OS architecture) per reference, 4 bytes per Integer, 8 bytes per Long, etc. Depending on the heap dump format the size may be adjusted (e.g. aligned to 8, etc…) to model better the real consumption of the VM. Retained SetRetained set of X is the set of objects which would be removed by GC when X is garbage collected. Retained HeapRetained heap of X is the sum of sha...
JVM进阶 -- JDK命令
jpsLists the instrumented Java Virtual Machines (JVMs) on the target system.如果Java进程关闭了默认开启的UsePerfData参数(**-XX:-UsePerfData),那么jps/jstat将无法探知**到该Java进程 123$ jps1408 Jps19 LiveCoverMain 参数 备注 m Displays the arguments passed to the main method. The output may be null for embedded JVMs. l Displays the full package name for the application’s main class or the full path name to the application’s JAR file. v Displays the arguments passed to the JVM. jstatMonitors Java Virtual Machine (JVM) ...
JVM进阶 -- 浅谈注解处理器
注解与注解处理器 注解是Java 5引入,用来为类、方法、字段和参数等Java结构提供额外信息的机制 @Override仅对Java编译器有用,为Java编译器引用一条新的编译规则,编译完成后,它的使命也结束了 Java的注解机制允许开发人员自定义注解,这些自定义注解同样可以为Java编译器添加编译规则 这种功能需要由开发人员提供,并且以插件的形式接入Java编译器中,这些插件被称之为注解处理器 除了引入新的编译规则外,注解处理器还可以用于修改已有的Java源文件(不推荐)和生成新的Java源文件 123456789@Target(ElementType.METHOD)@Retention(RetentionPolicy.SOURCE)public @interface Override {}// 元注解@Target:用来限定目标注解所能标注的Java结构// 元注解@Retention:用来限定目标注解的生命周期// SOURCE:源代码,一旦源代码被编译为字节码,注解便会被擦除// CLASS:源代码+字节码// RUNTIME:源代码+字节...
JVM进阶 -- 浅谈循环优化
循环无关代码外提外提无关代码 循环无关代码:循环中值不变的表达式 在不改变程序语义的情况下,将循环无关代码提出循环外 那么程序将避免重复执行这些表达式,从而达到性能提升的效果 1234567int foo(int x, int y, int[] a) { int sum = 0; for (int i = 0; i < a.length; i++) { sum += x * y + a[i]; } return sum;} 123456789101112131415161718192021222324252627// 对应的字节码int foo(int, int, int[]); Code: 0: iconst_0 1: istore 4 3: iconst_0 4: istore 5 6: goto 25// 循环体开始 9: iload 4 // load sum 11: iload_1 // load x 12: ...
JVM进阶 -- 浅谈字段访问优化
概念在实际中,Java程序中的对象或许本身就是逃逸的,或许因为方法内联不够彻底而被即时编译器当成是逃逸的,这两种情况都将导致即时编译器无法进行标量替换,这时,针对对象字段访问的优化显得更为重要。 1234static int bar(Foo o, int x) { o.a = x; return o.a;} 对象o是传入参数,不属于逃逸分析的范围(JVM中的逃逸分析针对的是新建对象) 该方法会将所传入的int型参数x的值存储至实例字段Foo.a中,然后再读取并返回同一字段的值 这段代码涉及两次内存访问操作:存储和读取实例字段Foo.a 代码可以手工优化成如下 1234static int bar(Foo o, int x) { o.a = x; return x;} 即时编译器也能作出类似的自动优化 字段读取优化 即时编译器会优化实例字段和静态字段的访问,以减少总的内存访问次数 即时编译器将沿着控制流,缓存各个字段存储节点将要存储的值,或者字段读取节点所得到的值 当即时编译器遇到对同一字段的读取节点时,如果缓存值还没有失效,那么将...
JVM进阶 -- 浅谈逃逸分析
概念 在JVM即时编译语境下,逃逸分析将判断新建的对象是否逃逸 即时编译器判断对象是否逃逸的依据 对象是否被存入堆中(静态字段或者堆中对象的实例字段) 堆是线程共享的,其他线程可以获得该对象的引用 对象是否被传入未知代码 JVM即时编译是以方法为单位的 对于方法中未被内联的方法调用,即时编译器会将其当做未知代码 方法调用的调用者以及参数是逃逸的 注:方法内联可以简单理解,在即时编译过程中遇到方法调用时 将目标方法的方法体纳入到编译范围之中,并取代原方法调用的优化手段 foreach语法糖 12345public void forEach(ArrayList<Object> list, Consumer<Object> f) { for (Object obj : list) { f.accept(obj); }} 等价代码 1234567public void forEach(ArrayList<Object> list, Consumer<Object> f) ...
JVM基础 -- 字节码
操作数栈 JVM是基于栈的计算模型 在解析过程中,每当为Java方法分配栈帧时 执行每条执行之前,JVM要求该指令的操作数已被压入操作数栈中 在执行指令时,JVM会将该指令所需要的操作数弹出,并将该指令的结果重新压入栈中 iadd 执行iadd之前,栈顶的元素为int值1和int值2 执行iadd指令会将弹出这两个int,并将求得的和int值3压入栈中 iadd只消耗栈顶的两个元素,iadd并不关心更远的元素,也不会对它们进行修改 dup + pop dup和pop只能处理非long和非double类型的值 long类型和double类型需要占据两个栈单元,对应使用dup2和pop2 dup dup:复制栈顶元素 dup指令常用于复制new指令生成的未经初始化的引用 123456789101112131415public void dup() { Object o = new Object();}// 对应的字节码public void dup(); descriptor: ()V flags: ACC_PUBLIC Code: stack=2...














