你要如何衡量你的人生

坚持,努力,让好事发生

JVM 内置了自动内存分配管理机制。这个机制可以大大降低手动分配回收机制可能带来的内存泄露和内存溢出风险,使 Java 开发人员不需要关注每个对象的内存分配以及回收,从而更专注于业务本身。

JVM 自动内存分配管理机制的好处很多,但实则是把双刃剑。这个机制在提升 Java 开发效率的同时,也容易使 Java 开发人员过度依赖于自动化,弱化对内存的管理能力,这样系统就很容易发生 JVM 的堆内存异常,垃圾回收(GC)的方式不合适以及 GC 次数过于频繁等问题,这些都将直接影响到应用服务的性能。

JVM的内存划分中,有部分区域是线程私有的,有部分是属于整个JVM进程;有些区域会抛出OOM异常,有些则不会,了解JVM的内存区域划分以及特征,是定位线上内存问题的基础。那么JVM内存区域是怎么划分的呢?

运行中的Java进程内存占用情况

 Java虚拟机运行时数据区 - 大小和实际内存大小有差距
Java虚拟机运行时数据区 (仅参考模型)

 Java虚拟机运行时数据区-大概比例
Java虚拟机运行时数据区-大概比例

1. Java内存区域

Java虚拟机在执行Java程序的过程中会把它管理的内存划分为若干个不同的数据区域,这些区域都有各自的用途,以及创建和销毁的时间,有的随着虚拟机进程启动而存在,有的区域则依赖于用户线程的启动和结束而建立和销毁。

根据《Java 虚拟机规范》的规定,Java 虚拟机所管理的内存一共分为 Program Counter Register(程序计数器)、VM Stack(虚拟机栈)、Native Method Stack(本地方法栈)、Heap(堆)、Method Area(方法区)五个区域。

1.1 程序计数器(Program Counter Register)

程序计数器(Program Counter Register),简称PC,在JVM规范中,每个线程都有自己的程序计数器。

这是一块比较小的内存空间,存储当前线程正在执行的Java方法的JVM指令(或操作码)地址,即字节码的行号。如果当前方法是 native 方法,那么程序计数器的值为 undefined。

举个例子,下面是一段输出 Hello World 的代码,代码和反编译后的文件如下:

public class HelloWorld{
	public static void main(String[] args){
		System.out.println("Hello, World!");
	}
}
Classfile /home/wkq/workspaces/java_test/HelloWorld.class
  Last modified Jun 21, 2020; size 427 bytes
  SHA-256 checksum cc0de3eb12561fe81dfb95961d817665276587839bdf652b6f4070c1b9942f10
  Compiled from "HelloWorld.java"
public class HelloWorld
  minor version: 0
  major version: 58
  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
  this_class: #21                         // HelloWorld
  super_class: #2                         // java/lang/Object
  interfaces: 0, fields: 0, methods: 2, attributes: 1
Constant pool:
   #1 = Methodref          #2.#3          // java/lang/Object."<init>":()V
   #2 = Class              #4             // java/lang/Object
   #3 = NameAndType        #5:#6          // "<init>":()V
   #4 = Utf8               java/lang/Object
   #5 = Utf8               <init>
   #6 = Utf8               ()V
   #7 = Fieldref           #8.#9          // java/lang/System.out:Ljava/io/PrintStream;
   #8 = Class              #10            // java/lang/System
   #9 = NameAndType        #11:#12        // out:Ljava/io/PrintStream;
  #10 = Utf8               java/lang/System
  #11 = Utf8               out
  #12 = Utf8               Ljava/io/PrintStream;
  #13 = String             #14            // Hello, World!
  #14 = Utf8               Hello, World!
  #15 = Methodref          #16.#17        // java/io/PrintStream.println:(Ljava/lang/String;)V
  #16 = Class              #18            // java/io/PrintStream
  #17 = NameAndType        #19:#20        // println:(Ljava/lang/String;)V
  #18 = Utf8               java/io/PrintStream
  #19 = Utf8               println
  #20 = Utf8               (Ljava/lang/String;)V
  #21 = Class              #22            // HelloWorld
  #22 = Utf8               HelloWorld
  #23 = Utf8               Code
  #24 = Utf8               LineNumberTable
  #25 = Utf8               main
  #26 = Utf8               ([Ljava/lang/String;)V
  #27 = Utf8               SourceFile
  #28 = Utf8               HelloWorld.java
{
  public HelloWorld();
    descriptor: ()V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 1: 0

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #13                 // String Hello, World!
         5: invokevirtual #15                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: return
      LineNumberTable:
        line 3: 0
        line 4: 8
}
SourceFile: "HelloWorld.java"

LineNumberTable,是指每一个java字节码指令对应java代码文件中的第几行,以方便定位。

LineNumberTable:
  line 3: 0
  line 4: 8

其中 line 3 line 4 指的的代码中的行号, 0 8 指的是 java字节码的指令

该内存区域是唯一一个在Java虚拟机规范中没有规定任何 OutOfMemoryError 情况的内存区域。

1.2 Java虚拟机栈(Java Virtal Machine Stack)

Java虚拟机栈(Java Virtal Machine Stack),同样也是属于线程私有区域,该区域存储着局部变量表,编译时期可知的各种基本类型数据、对象引用、方法出口等信息。

局部变量表存放了编译期可知的各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用和returnAddress类型(指向了一条字节码指令的地址)。
其中64位长度的long和double类型的数据会占用2个局部变量空间(slot),其余的数据类型占1个。

局部变量表所需的内存空间在编译期间分配完成,当进入一个方法时,这个方法需要在帧中分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表的大小。

在这个java栈中又会包含多个栈帧,每运行一个方法就创建一个栈帧,用于存储局部变量表、操作栈、方法返回值等。每一个方法从调用直至执行完成的过程,就对应一个栈帧在java栈中入栈到出栈的过程。
每次方法调用时,一个新的栈帧创建并压栈到栈顶。当方法正常返回或抛出未捕获的异常时,栈帧就会出栈。除了栈帧的压栈和出栈,栈不能被直接操作。所以可以在堆上分配栈帧,并且不需要连续内存。

栈可以是动态分配也可以固定大小。
如果线程请求一个超过允许范围的空间,就会抛出一个StackOverflowError。
如果线程需要一个新的栈帧,但是没有足够的内存可以分配,就会抛出一个 OutOfMemoryError。

阅读全文 »

  1. 下载解压orientdb压缩包
  2. 通过 server.sh 或者 server.bat 启动orieintdb
  3. 访问 http://localhost:2480 查看orientdb

1 下载解压

orientdb 所有版本
https://orientdb.com/releases/
https://orientdb.com/downloads/
https://orientdb.com/download-2/
https://orientdb.org/download

orientdb-3.0.8.zip https://orientdb3.s3.us-east-2.amazonaws.com/releases/3.0.8/orientdb-3.0.8.zip
orientdb-3.0.8.tar.gz https://orientdb3.s3.us-east-2.amazonaws.com/releases/3.0.8/orientdb-3.0.8.tar.gz
agent-3.0.8.jar https://orientdb3.s3.us-east-2.amazonaws.com/releases/3.0.8/agent-3.0.8.jar

无论是zip包还是tar.gz包,解压完进入bin目录,执行 ./server.sh (linux) 或 server.bat(windows) 即可运行OrientDB数据库。
第一次使用需要设置密码,设置完密码启动后在浏览器输入 http://127.0.0.1:2480 访问 图形化界面。

阅读全文 »

集群内的原理

介绍 cluster 、 node 、 shard 等常用术语,Elastisearch 的扩容机制, 以及如何处理硬件故障的内容。

ElasticSearch 的主旨是随时可用和按需扩容。 而扩容可以通过购买性能更强大( 垂直扩容 ,或 纵向扩容 ) 或者数量更多的服务器( 水平扩容 ,或 横向扩容 )来实现。

虽然 Elasticsearch 可以获益于更强大的硬件设备,但是垂直扩容是有极限的。 真正的扩容能力是来自于水平扩容–为集群添加更多的节点,并且将负载压力和稳定性分散到这些节点中。

(1) 空集群

一个运行中的 Elasticsearch 实例称为一个 节点,而集群是由一个或者多个拥有相同 cluster.name 配置的节点组成, 它们共同承担数据和负载的压力。当有节点加入集群中或者从集群中移除节点时,集群将会重新平均分布所有的数据。

(2) 集群健康

查看集群健康状态

http://localhost:9200/_cluster/health?pretty

$ curl -X GET "localhost:9200/_cluster/health?pretty"
{
  "cluster_name" : "my-application",
  "status" : "yellow",
  "timed_out" : false,
  "number_of_nodes" : 1,
  "number_of_data_nodes" : 1,
  "active_primary_shards" : 5,
  "active_shards" : 5,
  "relocating_shards" : 0,
  "initializing_shards" : 0,
  "unassigned_shards" : 5,
  "delayed_unassigned_shards" : 0,
  "number_of_pending_tasks" : 0,
  "number_of_in_flight_fetch" : 0,
  "task_max_waiting_in_queue_millis" : 0,
  "active_shards_percent_as_number" : 50.0
}

status 字段指示着当前集群在总体上是否工作正常。它的三种颜色含义如下:
green 所有的主分片和副本分片都正常运行。
yellow 所有的主分片都正常运行,但不是所有的副本分片都正常运行。
red 有主分片没能正常运行。

阅读全文 »

查看正在执行的cypher语句

1、查看自己当前正在运行的所有查询。语法为: CALL dbms.listQueries()
2. 找到正在运行的语句的id
3. 调用 CALL dbms.killQueries([‘query-1’,‘query-2’]) 根据id杀掉 语句执行的进程

Neo4j备份

Neo4j备份的内容是某一时刻的完整数据库

CALL apoc.export.csv.all('/data/neo4j/export/graph_all.csv', null); 全量export

阅读全文 »

转自 Java 最常见的 200+ 面试题:面试必备

一、Java 基础

1.JDK 和 JRE 有什么区别?

2.== 和 equals 的区别是什么?

3.两个对象的 hashCode()相同,则 equals()也一定为 true,对吗?

4.final 在 java 中有什么作用?

5.java 中的 Math.round(-1.5) 等于多少?

6.String 属于基础的数据类型吗?

7.java 中操作字符串都有哪些类?它们之间有什么区别?

8.String str=”i”与 String str=new String(“i”)一样吗?

9.如何将字符串反转?

10.String 类的常用方法都有那些?

阅读全文 »

在实际的使用时,经常遇到这么一个问题,我要从某种数据库中查询出数据,但是不告诉你字段/属性。
乍一看,这个怎么可能,不告诉我字段/属性,要把数据查出来,后来在github上看见一段代码,读了这段代码后恍然大悟。还是 too young to simple

原理是通过JDBC的getMetaData()方法来获取表结构,里面用到了反射 (进行了处理,高并发下还是不建议使用)
比较重要的一点是查询的时候数据库有数据字典,可以根据数据字典获取所有字段/属性

实测,MySQL 可用
代码如下


import java.sql.Connection;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * 通用接口<br>
 *
 * @author weikeqin.cn@gmail.com
 * @version V1.0
 * @date 2017-07-11 15:12
 */
public interface Executor {

    /**
     * 查询接口
     *
     * @param sql    查询语句
     * @param params 占位符对应的参数
     * @param conn   连接
     * @return Iterator<LinkedHashMap<String, Object>>
     * @throws SQLException
     */
    Iterator<Map<String, Object>> query(String sql, Map<Integer, Object> params, Connection conn) throws SQLException;

    /**
     * (单条)增删改接口
     *
     * @param sql    增删改语句
     * @param params 占位符对应的参数
     * @param conn   连接
     * @return 操作的条数
     * @throws SQLException
     */
    int operat(String sql, Map<Integer, Object> params, Connection conn) throws SQLException;

    /**
     * 批量操作<br>
     * 大于等于0是成功处理的
     *
     * @param sql  增删改语句
     * @param list 占位符对应的参数
     * @param conn 连接
     * @return
     * @throws SQLException
     * @author : weikeqin.cn@gmail.com
     * @date : 2017-09-08 14:47:15
     */
    int[] betchOperat(String sql, List<Map<Integer, Object>> list, Connection conn) throws SQLException;

}
阅读全文 »

tf-idf的具体实现,代码稍后上传到github

在进行文本特征选择的时候,有很多种方法,tf-idf是比较简单常用的一种。
tf-idf选择出的是有区分度的词,对选特征词有很大的帮助。

TF-IDF(term frequency–inverse document frequency)是一种用于资讯检索与资讯探勘的常用加权技术。

 TFIDF的主要思想是:如果某个词或短语在一篇文章中出现的频率TF高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。

假如一篇文件的总词语数是100个,而词语”蜜蜂”出现了3次,那么”蜜蜂”一词在该文件中的词频就是3/100=0.03。
一个计算文件频率 (DF) 的方法是测定有多少份文件出现过”蜜蜂”一词,然后除以文件集里包含的文件总数。
所以,如果”蜜蜂”一词在2份文件出现过,而文件总数是8份的话,其逆向文件频率就是 lg(8/2)=2。最后的TF-IDF的分数为 0.03 * 2 = 0.06。

阅读全文 »

在比较排序算法时,得先找一个标准比较,一般都使用时间复杂度和空间复杂度来衡量。

排序算法
 根据排序过程中使用的存储器不同,排序算法分为 内部排序 和 外部排序 两大类。
  内部排序指的是待排序记录存放在计算机随机存储器中进行的排序过程
  外部排序指的在排序过程中尚需对外村进行访问的排序过程


/**
 * 交换数组元素
 *
 * @param array
 * @param i
 * @param j
 */
public static void swap(int[] array, int i, int j) {
	int tmp = array[i];
	array[i] = array[j];
	array[j] = tmp;
}


/**
 * 交换数组元素
 *    用了一个巧妙的方法,不需要临时变量
 *    不足之处,就是当数组中的arr[a]+arr[b]的值大于int的最大值时,计算结果会溢出。导致arr[a]和arr[b]的值错误。
 * @param arr
 * @param a
 * @param b
 */
public static void swap(int[] arr, int a, int b){
	arr[a] = arr[a] + arr[b];
	arr[b] = arr[a] - arr[b];
	arr[a] = arr[a] - arr[b];
}


/**
 * 交换数组元素
 * 
 * @param arr
 * @param a
 * @param b
 */
public void swap(int[] arr, int a, int b) {
    arr[a] ^= arr[b];
    arr[b] ^= arr[a];
    arr[a] ^= arr[b];
}

阅读全文 »

Hexo博客 Next主题

(1) Next主题

Next主题有多个版本

时间 版本 仓库地址 对应官网
2014 ~ 2017 0.1.0 ~ 5.1.4 https://github.com/iissnan/hexo-theme-next -
2018 ~ 2019 6.0.0 ~ 7.8.0 https://github.com/theme-next/hexo-theme-next https://theme-next.org/index.html
2020 ~ 至今 8.0.0 ~ https://github.com/next-theme/hexo-theme-next https://theme-next.js.org/

https://github.com/next-theme/hexo-theme-next/issues/4

https://github.com/next-theme/hexo-theme-next/issues/4#issuecomment-626205848

(1.1) Next主题配置文件

Next主题 6.x 7.x 8.x的配置在 blog/_config.next.yml,目的是为了和next主题的_config.yml解耦,同时解决每次merge合并代码冲突的烦恼。


(2) 主题通用配置

配置文件使用 blog/_config.next.yml

(2.1) 主题风格

NexT主题 风格为 Muse

# ---------------------------------------------------------------
# Scheme Settings
# ---------------------------------------------------------------

# Schemes
scheme: Muse
#scheme: Mist
#scheme: Pisces
#scheme: Gemini

(2.2) 侧边栏标题配置

# 侧边栏中的目录(标题)配置
toc:
  enable: true
  # 自动将列表(标题)编号添加到目录中。
  number: false
  # 如果为 true,则当标题宽度长于侧边栏宽度时,所有单词都将放置在下一行。
  wrap: false
  # 如果为 true,则将显示帖子中所有级别的目录,而不是其中激活的部分。
  expand_all: false
  # 生成目录(标题)的最大深度。  最多支持6级标题 ###### 
  max_depth: 6

(3) 个性化设置

修改blog的 $blog/_config.next.yml 文件
修改后如下

# filepath: blog/_config.next.yml

# Define custom file paths.
# Create your custom files in site directory `source/_data` and uncomment needed files below.
custom_file_path:
  #head: source/_data/head.njk
  #header: source/_data/header.njk
  #sidebar: source/_data/sidebar.njk
  #postMeta: source/_data/post-meta.njk
  #postBodyEnd: source/_data/post-body-end.njk
  #footer: source/_data/footer.njk
  #bodyEnd: source/_data/body-end.njk
  variable: source/_data/variables.styl
  #mixin: source/_data/mixins.styl
  style: source/_data/styles.styl

v6.x v7.x v8.x 都支持上面这种方法

Next主题个性化文件

Hexo + NexT8主题配置透明背景过程踩坑小记


(3.1) style配置

(3.1.1) 设置背景

修改 blog/source/_data/styles.styl 文件,添加以下配置

// source/_data/styles.styl

// background
body {
  background-image:url(../images/background.jpg);
  height:100%;
  width:100%;
  background-repeat:repeat-x;
  background-attachment:fixed; //不滚动
  background-size:100% 100%;  //填充
}

(3.1.2) 设置透明度

修改 blog/source/_data/styles.styl 文件,添加以下配置


//###### 博客内容透明化 ######

//文章内容的透明度设置
//文章内容的透明度设置+文章边框设置
.post-block {
  margin-top: 60px;    // 内容
  margin-bottom: 60px;
  padding: 35px;       // 内容边框
  background: rgba(255,255,255,0.9) none repeat scroll !important; // 内容不透明
}

//分页(主页最下面的那一小块)
.pagination {
  background: rgba(255,255,255,0.9);
}

//菜单栏背景
.header-inner {
  background: rgba(255,255,255,0.9);
}

//侧边框的透明度设置
.sidebar-inner {
  background: rgba(255,255,255,0.9) none repeat scroll !important;
}

//搜索框(local-search)的透明度设置
.popup {
  opacity: 0.9;
}

//评论区
.comments {
  background: rgba(255,255,255,0.9);
}

(3.2) variables配置

(3.2.1) 设置页面内容宽度

next主题默认配置在 blog/themes/next/source/css/_variables/base.styl

// Layout sizes
// --------------------------------------------------
$content-desktop                = 700px;
$content-desktop-large          = 800px;
$content-desktop-largest        = 900px;

$content-desktop-padding        = 40px;
$content-tablet-padding         = 10px;
$content-mobile-padding         = 8px;

需要添加自定义配置 source/_data/variables.styl

$content-desktop         = 80%
$content-desktop-large   = 85%
$content-desktop-largest = 90%

并且修改配置文件,blog的 blog/_config.next.yml
variable: source/_data/variables.styl 前面的#去掉

Hexo Next 主题优化
How-to-Change-Content-Width


(4) Next插件

(4.1) Next主题添加Waline评论系统

npm install @waline/hexo-next
# Waline 评论
# For more information: https://waline.js.org, https://github.com/walinejs/waline
waline:
  enable: true #是否开启
  serverURL: xxx # Waline #服务端地址,我们这里就是上面部署的 Vercel 地址
  placeholder: 欢迎评论 # #评论框的默认文字
  avatar: mm # 头像风格
  meta: [nick, mail, link] # 自定义评论框上面的三个输入框的内容
  pageSize: 10 # 评论数量多少时显示分页
  lang: zh-cn # 语言, 可选值: en, zh-cn
  # Warning: 不要同时启用 `waline.visitor` 以及 `leancloud_visitors`.
  visitor: false # 文章阅读统计
  comment_count: true # 如果为 false , 评论数量只会在当前评论页面显示, 主页则不显示
  requiredFields: [] # 设置用户评论时必填的信息,[nick,mail]: [nick] | [nick, mail]
  libUrl: # Set custom library cdn url

(4.2) Next主题添加3d小地球实时访客统计工具

Revolver Maps 是一个交互式的网站访客地图。每一个浏览者的位置都会实时在由 Canvas 渲染的地球上标记出来。
官网 https://www.revolvermaps.com/

改动点:
$blog/themes/next/layout/_partials/sidebar/site-overview.njk 文件尾部添加以下代码

<div class="revolvermaps">
    <script type="text/javascript" src="//rf.revolvermaps.com/0/0/6.js?i=5rcgvdncuwu&amp;m=7&amp;c=e63100&amp;cr1=ffffff&amp;f=arial&amp;l=0&amp;bv=90&amp;lx=-420&amp;ly=420&amp;hi=20&amp;he=7&amp;hc=a8ddff&amp;rs=80" async="async"></script>
</div>

参考文章
一行代码为你的网站添加一个3d小地球实时访客统计工具
Hexo5-在博客主页侧边栏添加网易云音乐外链&访问者地图
个人博客网站搭建与优化


参考资料

[1] Next主题自定义文件
[2] hexo-next主题优化
[3] Hexo之Next主题美化代码

[4] Hexo Next 主题优化
[5] How-to-Change-Content-Width

[6] 一行代码为你的网站添加一个3d小地球实时访客统计工具
[7] Hexo5-在博客主页侧边栏添加网易云音乐外链&访问者地图
[8] 个人博客网站搭建与优化

使用canal前需要准备以下几个内容

  1. 安装配置MySQL
    1.1 安装 mysql,
    1.2 配置 mysql binlog使用ROW模式
    1.3 在MySQL添加对应的canal用户
    1.4 检查canal用户生效
  2. 下载canal并配置
    2.1 下载canal
    2.2 配置 canal
    2.3 启动canal (需要JDK>=1.6.25)

(1) 配置MySQL

(1.1) 安装MySQL

参考 https://dev.mysql.com/doc/refman/5.7/en/installing.html

(1.2) 修改MySQL配置文件

canal的原理是基于mysql binlog技术,所以需要开启mysql的binlog写入功能,并且配置binlog模式为row.

[mysqld]  
log-bin=mysql-bin  # 开启 binlog
binlog-format=ROW  # 选择 ROW 模式
server_id=1        # 配置 MySQL replaction ,不能和 canal 的 slaveId 重复

(1.3) MySQL添加canal用户并授权

canal的原理是模拟自己为mysql slave,所以需要mysql slave的相关权限

CREATE USER canal IDENTIFIED BY 'canal';    

GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'canal'@'%';  

FLUSH PRIVILEGES; 
阅读全文 »
0%