00-谈GUI工具前的补充

补充1:内存泄漏

内存泄漏的理解与分类

何为内存泄漏( memory leak)

可达性分析算法来判断对象是否是不再使用的对象,本质都是判断一个对象是否还被引用。那么对于这种情况下,由于代码的实现不同就会出现很多种内存泄漏问题(让JVM误以为此对象还在引用中,无法回收,造成内存泄漏)。

内存泄漏( memory leak)的理解

严格来说,只有对象不会再被程序用到了,但是GC又不能回收他们的情况,才叫内存泄漏。

但实际情况很多时候一些不太好的实践(或疏忽)会导致对象的生命周期变得很长甚至导致OOM,也可以叫做宽泛意义上的“内存泄漏”。

对象X引用对象Y,X的生命周期比Y的生命周期长;
那么当Y生命周期结束的时候,X依然引用着Y,这时候,垃圾回收期是不会回收对象Y的;
如果对象x还引用着生命周期比较短的A、B、C,对象A又引用着对象 a、b、c,这样就可能造成大量无用的对象不能被回收,进而占据了内存资源,造成内存泄漏,直到内存溢出。

内存泄漏与内存溢出的关系:

1.内存泄漏(memory leak )
申请了内存用完了不释放,比如一共有1024M 的内存,分配了512M 的内存一直不回收,那么可以用的内存只有512M 了,仿佛泄露掉了一部分;
通俗一点讲的话,内存泄漏就是【占着茅坑不拉shi】。

2.内存溢出(out of memory)
申请内存时,没有足够的内存可以使用;
通俗一点儿讲,一个厕所就三个坑,有两个站着茅坑不走的(内存泄漏),剩下最后一个坑,厕所表示接待压力很大,这时候一下子来了两个人,坑位(内存)就不够了,内存泄漏变成内存溢出了。

可见,内存泄漏和内存溢出的关系: 内存泄漏的增多,最终会导致内存溢出。

泄漏的分类

经常发生:发生内存泄露的代码会被多次执行,每次执行,泄露一块内存;
偶然发生:在某些特定情况下才会发生;
一次性:发生内存泄露的方法只会执行一次;
隐式泄漏:一直占着内存不释放,直到执行结束;严格的说这个不算内存泄漏,因为最终释放掉了,但是如果执行时间特别长,也可能会导致内存耗尽。

Java中内存泄漏的8种情况

1-静态集合类

静态集合类,如HashMap、LinkedList等等。如果这些容器为静态的,那么它们的生命周期与JVM程序一致,则容器中的对象在程序结束之前将不能被释放,从而造成内存泄漏。简单而言,长生命周期的对象持有短生命周期对象的引用,尽管短生命周期的对象不再使用,但是因为长生命周期对象持有它的引用而导致不能被回收。

2-单例模式

单例模式,和静态集合导致内存泄露的原因类似,因为单例的静态特性,它的生命周期和JVM 的生命周期一样长,所以如果单例对象如果持有外部对象的引用,那么这个外部对象也不会被回收,那么就会造成内存泄漏。

3-内部类持有外部类

内部类持有外部类,如果一个外部类的实例对象的方法返回了一个内部类的实例对象。
这个内部类对象被长期引用了,即使那个外部类实例对象不再被使用,但由于内部类持有外部类的实例对象,这个外部类对象将不会被垃圾回收,这也会造成内存泄漏。

4-各种连接,如数据库连接、网络连接和IO连接等

各种连接,如数据库连接、网络连接和IO连接等。

在对数据库进行操作的过程中,首先需要建立与数据库的连接,当不再使用时,需要调用close方法来释放与数据库的连接。只有连接被关闭后,垃圾回收器才会回收对应的对象。

否则,如果在访问数据库的过程中,对Connection、Statement或ResultSet不显性地关闭,将会造成大量的对象无法被回收,从而引起内存泄漏。

5-变量不合理的作用域

变量不合理的作用域。一般而言,一个变量的定义的作用范围大于其使用范围,很有可能会造成内存泄漏。另一方面,如果没有及时地把对象设置为null,很有可能导致内存泄漏的发生。

如下面的伪代码

如上面这个伪代码,通过readFronNet方法把接受的消息保存在变量msg中,然后调用saveDB方法把msg的内容保存到数据库中,此时msg已经就没用了,由于msg的生命周期与对象的生命周期相同,此时msg还不能回收,因此造成了内存泄漏。

实际上这个msg变量可以放在receiveMsg方法内部,当方法使用完,那么msg的生命周期也就结束,此时就可以回收了。还有一种方法,在使用完msg后,把msg设置为null,这样垃圾回收器也会回收msg的内存空间。

6-改变哈希值

改变哈希值,当一个对象被存储进HashSet集合中以后,就不能修改这个对象中的那些参与计算哈希值的字段了。

否则,对象修改后的哈希值与最初存储进HashSet集合中时的哈希值就不同了,在这种情况下,即使在contains方法使用该对象的当前引用作为的参数去HashSet集合中检索对象,也将返回找不到对象的结果,这也会导致无法从HashSet集合中单独删除当前对象,造成内存泄漏。

这也是 string为什么被设置成了不可变类型,我们可以放心地把 String存入 HashSet,或者把String当做HashMap 的key值;

当我们想把自己定义的类保存到散列表的时候,需要保证对象的 hashCode 不可变。

7-缓存泄漏

内存泄漏的另一个常见来源是缓存,一旦你把对象引用放入到缓存中,他就很容易遗忘。比如:之前项目在一次上线的时候,应用启动奇慢直到夯死,就是因为代码中会加载一个表中的数据到缓存(内存)中,测试环境只有几百条数据,但是生产环境有几百万的数据。

对于这个问题,可以使用WeakHashMap代表缓存,此种Map的特点是,当除了自身有对key的引用外,此key没有其他引用那么此map会自动丢弃此值。

8-监听器和回调

内存泄漏第三个常见来源是监听器和其他回调,如果客户端在你实现的API中注册回调,却没有显示的取消,那么就会积聚。

需要确保回调立即被当作垃圾回收的最佳方法是只保存它的弱引用,例如将他们保存成为WeakHashMap中的键。

补充2:支持使用OQL语言查询对象信息

MAT支持一种类似于SQL的查询语言OQL(Object Query Language)。OQL使用类SQL语法,可以在堆中进行对象的查找和筛选。

SELECT子句

在NAT中,Select子句的格式与SQL基本一致,用于指定要显示的列。Select子句中可以使用“*”,查看结果对象的引用实例(相当于outgoing references)。

SELECT * FROM java.util.Vector v

使用“OBECTS”关键字,可以将返回结果集中的项以对象的形式显示。

SELECT objects v.elementData FROM java.util.Vector v
SELECT OBECTS s.value FROM java.lang.String s

在Select子句中,使用“AS RETAINED SET”关键字可以得到所得对象的保留集。

SELECT AS RETAINED SET *FROM com.fs.mat. Student

“DISTINCT”关键字用于在结果集中去除重复对象。

SELECT DISTINCT OBJECTS classof(s)FROM java.lang.String s

FROM子句

From子句用于指定查询范围,它可以指定类名、正则表达式或者对象地址。

SELECT *FROM java. lang.String s

下例使用正则表达式,限定搜索范围,输出所有com.fs包下所有类的实例

SELECT *FROM “com\ .fs…*”

也可以直接使用类的地址进行搜索。使用类的地址的好处是可以区分被不同ClassLoader加载的同一种类型。

select* from 0x37a0b4d

WHERE子句

Where子句用于指定0QL的查询条件。0QL查询将只返回满足where子句指定条件的对象。Where子句的格式与传统SQL极为相似。

下例返回长度大于10的char数组。

SELECT* FROM char[] s WHERE s.@length>10

下例返回包含“java”子字符串的所有字符串,使用“LIKE”操作符,“LIKE”操作符的操作参数为正则表达式。

SELECT * FROM java.lang.String s WHERE toString(s)LIKE “.*java.*”

下例返回所有value域不为null的字符串,使用“=”操作符。

SELECT * FROM java.lang.String s where s.value!=null

Where子句支持多个条件的AND、OR运算。下例返回数组长度大于15,并且深堆大于1000字节的所有Vector对象。

SELECT * FROM java.util.Vector v WHERE v.elementData.@length>15 AND v.@retainedHeapsize>1000

内置对象与方法

0QL中可以访问堆内对象的属性,也可以访问堆内代理对象的属性。访问堆内对象的属性时,格式如下:
[ <alias>. ] <field> . <field>. <field>其中alias为对象名称。

访问java.io.File对象的path属性,并进一步访问path的value属性:

SELECT toString(f.path.value) FROM java.io.File f

下例显示了String对象的内容、objectid和objectAddress。

SELECT s.toString(),s.@objectId,s.@objectAddress FROMjava.lang.String s

下例显示java.util.Vector内部数组的长度。

SELECT v.elementData.@length FROM java.util.Vector v

下例显示了所有的java.util.Vector对象及其子类型

select *from INSTANCEOF java.util.Vector

01-工具概述

使用命令行工具或组合能帮您获取目标Java应用性能相关的基础信息,但它们存在下列局限:
1.无法获取方法级别的分析数据,如方法间的调用关系、各方法的调用次数和调用时间等(这对定位应用性能瓶颈至关重要)。

2.要求用户登录到目标Java应用所在的宿主机上,使用起来不是很方便。3.分析数据通过终端输出,结果展示不够直观。

为此,JDK提供了一些内存泄漏的分析工具,如jconsole,jvisualvm等,用于辅助开发人员定位问题,但是这些工具很多时候并不足以满足快速定位的需求。所以这里我们介绍的工具相对多一些、丰富一些。

图形化综合诊断工具

JDK自带的工具

jconsole

jconsole:JDK自带的可视化监控工具。查看Java应用程序的运行概况、监控堆信
息、永久区(或元空间)使用情况、类加载情况等
—>位置:jdk \bin\jconsole.exe

Visual VM

Visual VM是一个工具,它提供了一个可视界面,用于查看Java虚拟机上运行的基于Java技术的应用程序的详细信息。
—>位置:jdk\binljvisualvm.exe

JMC:Java Mission Control

JMC:Java Mission Control,内置Java Flight Recorder。能够以极低的性能开销收集Java虚拟机的性能数据。

第三方工具

MAT:MAT(Memory Analyzer Tool)

MAT:MAT(Memory Analyzer Tool)是基于Eclipse的内存分析工具,是一个快
速、功能丰富的Java heap分析工具,它可以帮助我们查找内存泄漏和减少内存消耗
—>Eclipse的插件形式

JProfiler

JProfiler:商业软件,需要付费。功能强大。
—>与VisualVM类似 I

Arthas

Arthas:Alibaba开源的Java诊断工具。深受开发者喜爱。

Btrace

Btrace:Java运行时追踪工具。可以在不停机的情况下,跟踪指定的方法调用、构
造函数调用和系统内存等信息。

02-jConsole 了解

基本概述

从Java5开始,在JDK中自带的java监控和管理控制台。
用于对JVM中内存、线程和类等的监控,是一个基于JMX(java management extensions)的GUI性能监控工具。

官方教程:
https://docs.oracle.com/javase/7/docs/technotes/guides/management/jconsole.htm1

启动

cmd命令启动(需要配置环境变量)



三种连接方式

Local

使用JConsole连接一个正在本地系统运行的JVM,并且执行程序的和运行JConsole的需要
是同一个用户。JConsole使用文件系统的授权通过RMI连接器连接到平台的MBean服务器上。
这种从本地连接的监控能力只有Sun的JDK具有。

Remote

使用下面的URL通过RMI连接器连接到一个JMX代理,servicejm.rmi://jindi/rmi:/hostName:portNum/jimkrmi。
JConsole为建立连接,需要在环境变量中设置mx.remote.credentials来指定用户名和密码,从而进行授权。

Advanced

使用一个特殊的URL连接JMX代理。一般情况使用自己定制的连接器而不是RMI提供的连接器
来连接JMX代理,或者是一个使用JDK1.4的实现了JMX和JMX Rmote的应用。

03-Visual VM 重要

基本概述

Visual VM是一个功能强大的多合一故障诊断和性能监控的可视化工具。

它集成了多个JDK命令行工具,使用visual VM可用于显示虚拟机进程及进程的配置和环境信息(jps,jinfo),监视应用程序的CPU、GC、堆、方法区及线程的信息(jstat、jstack)等,甚至代替JConsole。

在JDK 6 Update 7以后,Visual VM便作为JDK的一部分发布(VisualVM在JDK/bin目录下),即:它完全免费。

此外,Visual VM也可以作为独立的软件安装:

首页: https: //visualvm.github.io/index.html

插件的安装

Visual VM的一大特点是支持插件扩展,并且插件安装非常方便。我们既可以通过离线下载插件文件*.nbm,然后在Plugin对话框的已下载页面下,添加已下载的插件。也可以在可用插件页面下,在线安装插件。(这里建议安装上:VisualGC)

插件地址: https://visualvm.github.io/pluginscenters.html



安装VisualGC插件

连接方式

本地连接

监控本地Java进程的CPU、类、线程等

远程连接

1-确定远程服务器的ip地址
2-添加JMX(通过JMX技术具体监控远端服务器哪个Java进程
3-修改bin/catalina.sh文件,连接远程的tomcat
4-在…/conf中添加jmxremote.access和jmxremote.password文件
5-将服务器地址改为公网ip地址
6-设置阿里云安全策略和防火墙策略
7-启动tomcat,查看tomcat启动日志和端口监听
8-JMX中输入端口号、用户名、密码登录

主要功能

1-生成/读取堆内存快照


查看其他dump文件

2-查看JVM参数和系统属性

3-查看运行中的虚拟机进程

4-生成/读取线程快照


5.程序资源的实时监控

6.其他功能
远程环境监控
CPU分析和内存分析
JMX代理连接

04-eclipse MAT

MAT(Memory Analyzer Tool)工具是一款功能强大的Java堆内存分析器。可以用于查找内存泄漏以及查看内存消耗情况。

MAT是基于Eclipse开发的,不仅可以单独使用,还可以作为插件的形式嵌入在Eclipse中使用。是一款免费的性能分析工具,使用起来非常方便。大家可以在

https://www.eclipse.org/mat/downloads.php下载并使用MAT。

运行独立版本的内存分析器所需的最低 Java 版本是 Java 11。请参阅JRE/JDK 来源。

本次不做此工具的详解

05-JProfiler 重要

基本概述

介绍

在运行Java的时候有时候想测试运行时占用内存情况,这时候就需要使用测试工具查看了。在
eclipse里面有 Eclipse Memory Analyzer tool(MAT)插件可以测试,而在IDEA中也有这么一个插件,就是JProfiler。

JProfiler是由 ej-technologies 公司开发的一款 Java应用性能诊断工具。功能强大,但是收费。

官网下载地址: https : //www.ej-technologies.com/products/jprofiler/overview.html

特点

特点:
·使用方便、界面操作友好(简单且强大)
·对被分析的应用影响小(提供模板)
. CPU, Thread ,Memory分析功能尤其强大
·支持对jdbc , noSql,jsp, servlet, socket等进行分析
·支持多种模式(离线,在线)的分析
·支持监控本地、远程的VM
·跨平台,拥有多种操作系统的安装版本

主要功能

1-方法调用
对方法调用的分析可以帮助您了解应用程序正在做什么,并找到提高其性能的方法

2-内存分配
通过分析堆上对象、引用链和垃圾收集能帮您修复内存泄漏问题,优化内存使用

3-线程和锁
JProfiler提供多种针对线程和锁的分析视图助您发现多线程问题

4-高级子系统
许多性能问题都发生在更高的语义级别上。例如,对于JDBC调用,您可能希望找出
执行最慢的SQL语句。JProfiler支持对这些子系统进行集成分析

安装与配置

下载与安装

官网下载地址: https : //www.ej-technologies.com/products/jprofiler/overview.html
官方下载安装就是

JProfiler中配置IDEA

IDEA集成JProfiler


点击idea上面的JProfiler图标即可启动当前程序

具体使用



数据采集方式

JProfier数据采集方式分为两种:Sampling(样本采集)和Instrumentation(重构模式)

注:JProfiler本身没有指出数据的采集类型,这里的采集类型是针对方法调用的采集类型。因为Profiler的绝大多数核心功能都依赖方法调用采集的数据,所以可以直接认为是Profiler的数据采集类型。

lnstrumentation重构模式

.Instrumentation:这是JProfiler全功能模式。在class加载之前,JProfier把相关功能代码写入到需要分析的class的bytecode中,对正在运行的jvm有一定影响。

优点:功能强大。在此设置中,调用堆栈信息是准确的。
缺点:若要分析的class较多,则对应用的性能影响较大,CPU开销可能很高(取决于Filter的控制)。因此使用此模式一般配合Filter使用,只对特定的类或包进行分析

Sampling抽样模式(一般推荐使用此方式)

.Sampling:类似于样本统计,每隔一定时间(5ms)将每个线程栈中方法栈中的信息统计出来

优点:对CPU的开销非常低,对应用影响小(即使你不配置任何Filter)
缺点:一些数据/特性不能提供(例如:方法的调用次数、执行时间)

遥感监测Telemetries

内存视图Live Memory


Live memory 内存剖析: class/class instance的相关信息。例如对象的个数,大小,对象创建的方法执行栈,对象创建的热点。

所有对象A11 0bjects

显示所有加载的类的列表和在堆上分配的实例数。只有Java 1.5(JVMTI)才会显示此视图。

记录对象 Record objects

查看特定时间段对象的分配,并记录分配的调用堆栈。

分配访问树Allocation Call Tree

显示一棵请求树或者方法、类、包或对已选择类有带注释的分配信息的J2EE组件。

分配热点 Allocation Hot Spots

显示一个列表,包括方法、类、包或分配已选类的72EE组件。你可以标注当前值并且显示差异值。对于每个热点都可以显示它的跟踪记录树。

类追踪器class Tracker

类跟踪视图可以包含任意数量的图表,显示选定的类和包的实例与时间。

堆遍历heap walker

cpu视图cpu views

线程视图threads

Profiler通过对线程历史的监控判断其运行状态,并监控是否有线程阻塞产生,还能将一个线程所管理的方法以树状形式呈现。对线程剖析。

线程分析主要关心三个方面:

  1. web容器的线程最大数。比如: Tomcat的线程容量应该略大于最大并发数。
  2. 线程阻塞
  3. 线程死锁

线程历史Thread History

显示一个与线程活动和线程状态在一起的活动时间表。

线程监控Thread Monitor

显示一个列表,包括所有的活动线程以及它们目前的活动状况。

线程转储 Thread Dumps

显示所有线程的堆栈跟踪。

监视器&锁Monitors&locks

监控和锁Monitors & Locks所有线程持有锁的情况以及锁的信息。观察VM的内部线程并查看状态:

死锁探测图表Current Locking Graph :显示JVM中的当前死锁图表。
目前使用的监测器 Current Monitors :显示目前使用的监测器并且包括它们的关联线程。
锁定历史图表Locking History Graph :显示记录在VM中的锁定历史。
历史检测记录 Monitor History :显示重大的等待事件和阻塞事件的历史记录。
监控器使用统计 Monitor Usage Statistics :显示分组监测,线程和监测类的统计监测数据

06-Arthas 阿里巴巴 建议查阅官方文档

基本概述

概述

Arthas(阿尔萨斯)是Alibaba开源的Java诊断工具,深受开发者喜爱。在线排查问题,无需重启;动态跟踪Java代码;实时监控JVM状态。

Arthas支持JDK 6+,支持Linux/Mac/Windows,采用命令行交互模式,同时提供丰富的Tab自动补全功能,进一步方便进行问题的定位和诊断。

官方使用文档

https://arthas.aliyun.com/doc/index.html

安装与使用

下载arthas

直接使用此链接https://arthas.aliyun.com/arthas-boot.jar下载

Arthas Spring Boot Starter

https://arthas.aliyun.com/doc/spring-boot-starter.html

配置maven依赖:

    <dependency><groupId>com.taobao.arthas</groupId><artifactId>arthas-spring-boot-starter</artifactId><version>${arthas.version}</version></dependency>

09-Flame Graphs(火焰图)

在追求极致性能的场景下,了解你的程序运行过程中cpu在干什么很重要,火焰图就是一种非常直观的展示cpu在程序整个生命周期过程中时间分配的工具。
火焰图对于现代的程序员不应该陌生,这个工具可以非常直观的显示出调用栈中的CPU消耗瓶颈。
网上的关于java火焰图的讲解大部分来自于Brendan Gregg的博客:
http://www.brendangregg.com/flamegraphs.html

JVM学习笔记之-JVM性能监控-JVM监控及诊断工具-GUI方式-Visual VM-JProfiler-Arthas相关推荐

  1. JVM 学习笔记二十六、JVM监控及诊断工具-GUI篇

    二十六.JVM监控及诊断工具-GUI篇 1.工具概述 使用上一张命令行工具或组合能帮您获取目标Java应用性能相关的基础信息,但他们存在下列局限: (1)无法获取方法级别的分析数据,如方法间的调用关系 ...

  2. JVM 学习笔记二十五、JVM监控及诊断工具-命令行篇

    二十五.JVM监控及诊断工具-命令行篇 1.概述 性能诊断是软件工程师在日常工作中经常面对和解决的问题,在用户体验至上的今天,解决好应用软件的性能问题能带来非常大的收益. Java作为最流行的编程语言 ...

  3. JVM学习笔记(三):JVM基本参数

    1 来源 来源:<Java虚拟机 JVM故障诊断与性能优化>--葛一鸣 章节:第三章 本文是第三章的一些笔记整理. 2 GC日志:-Xlog:gc 要打印GC日志的话,可以加上-Xlog: ...

  4. JVM学习笔记-02-JVM的体系结构

    JVM学习笔记-02-JVM的体系结构 文章目录 JVM学习笔记-02-JVM的体系结构 1. JVM的位置 2. JVM的体系结构 3.垃圾回收GC 4.JVM调优 视频链接-最新JVM教程IDEA ...

  5. 【JVM 学习笔记 05】:JVM性能调优工具的使用和优化案例

    [JVM 学习笔记 05]:JVM性能调优工具的使用 1. 使用 jstat(命令行工具) 查看线上系统的JVM运行状况 1.1 常用命令 1.2 使用技巧 1.2.1 随着系统运行,每秒钟会在年轻代 ...

  6. JVM学习笔记(自用)

    JVM学习笔记(自用) 文章目录 JVM学习笔记(自用) 1.简介 2.程序计数器 3. 虚拟机栈 4. 方法区 5. 直接内存 6. 垃圾回收 Young Collection Young Coll ...

  7. JVM学习笔记之GUI监控工具

    目录 背景 jConsole 本地连接:连接本地计算机一个正在运行的JVM进程 远程连接:连接JMX代理 高级连接:使用特殊的URL连接JMX代理 VisualVM 插件安装 连接方式 本地连接:连接 ...

  8. 尚硅谷JVM下篇:性能监控与调优篇_03_JVM监控及诊断工具-GUI篇

    目录 文章目录 目录 01-工具概述 02-JConsole 基本概述 启动 三种连接方式 Local Remote Advanced 主要作用 1.概览 2.内存 3.线程 4.概要 03-Visu ...

  9. <JVM下篇:性能监控与调优篇>03-JVM监控及诊断工具-GUI篇

    笔记来源:尚硅谷JVM全套教程,百万播放,全网巅峰(宋红康详解java虚拟机) 同步更新:https://gitee.com/vectorx/NOTE_JVM https://codechina.cs ...

最新文章

  1. 保护您的IE浏览器安全
  2. AngularJS 使用ngOption实现下拉列表
  3. stm32之GPIO
  4. Tornado的同步API写法举例实现GET/POST/DELETE请求+Tornado获取post请求中的json数据(转载)
  5. 豆瓣爬取电影top250
  6. QQ游戏连连看的脚本
  7. 【STM32F042】使用NTC热敏电阻实现温度测量
  8. java程序员表情包_听说,这些表情包只有程序员才懂
  9. 烽火戏诸侯暂排第四,第四届橙瓜网络文学奖入围20年十佳仙侠大神
  10. 鹏业安装算量NETDWGCOM接口创建失败处理办法
  11. [大话技术]话聊有趣的23种设计模式
  12. Linux led_class子系统
  13. springboot基于webrtc和janus的视频会议流程图
  14. PPP with MPPE协议
  15. Flutter画中画自定义画中画
  16. Unity读取数据库的简单思路
  17. 跳表是个好东西你值得拥有!
  18. 仿微同商城后台API
  19. 3D激光雷达SLAM算法学习03——前端里程计方案
  20. 八月五日个人训练记录

热门文章

  1. PHP 学习 第一天
  2. linux文件属性和类型
  3. docker添加阿里云专属镜像
  4. Groovy 设计模式 -- 抽象工厂 模式
  5. 剑指offer试题(PHP篇一)
  6. LightOJ - 1027 数学期望
  7. Redis自定义动态字符串(sds)模块(二)
  8. mysql limit优化
  9. Day18 (一)类的加载器
  10. Nodejs进阶:使用DiffieHellman密钥交换算法