Hi there 👋

Welcome to my blog

Jdk编译记录

编译环境 操作系统: macOS Big Sur 11.4 20F71 x86_64 CPU架构: x86 BootStrap: zulu17.28.13-ca-jdk17.0.0-macosx_x64 编译版本: https://github.com/openjdk/jdk 下载jdk源码 git clone https://git.openjdk.java.net/jdk/ 根据发布版本记录切换到 jdk17-ga版本 git checkout jdk-17-ga 运行配置 构建之前彻底清空上一次编译结果 make dist-clean 配置 BootStrap JDK。编译jdk17需要jdk17,下载已经编译好的jdk作为BootStrap JDK 同一个终端下配置JAVA_HOME export JAVA_HOME=${jdk17 home} 最后执行bash configure, 处理WARN等日志 成功结果 Configuration summary: * Name: macosx-x86_64-server-release * Debug level: release * HS debug level: product * JVM variants: server * JVM features: server: 'cds compiler1 compiler2 dtrace epsilongc g1gc jfr jni-check jvmci jvmti management nmt parallelgc serialgc services shenandoahgc vm-structs zgc' * OpenJDK target: OS: macosx, CPU architecture: x86, address length: 64 * Version string: 17-internal+0-adhoc....

2021-10-03 · 1 min

对IDEA调优

工具 jps jstat -gcutil 9448 1000 jconsole.exe IDEA调优后的参数 -server -Xms3g -Xmx3g -XX:NewRatio=5 -Xss16m -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:ConcGCThreads=4 -XX:ReservedCodeCacheSize=512m -XX:+TieredCompilation -XX:SoftRefLRUPolicyMSPerMB=50 -ea -Dsun.io.useCanonCaches=false-Djava.net.preferIPv4Stack=true-XX:+HeapDumpOnOutOfMemoryError -XX:-OmitStackTraceInFastThrow 相关参数介绍 # custom IntelliJ IDEA VM options ##################JVM模式############################ # IDEA的JVM以Server模式启动(新生代默认使用ParNew) -server ##################内存分配############################ # 堆初始值占用3G,意味着IDEA启动即分配3G内存 -Xms3g # 堆最大值占用3G -Xmx3g # 强制JVM在启动时申请到足够的堆内存(否则IDEA启动时堆初始大小不足3g) -XX:+AlwaysPreTouch # 年轻代与老年代比例为1:3(默认值是1:4),降低年轻代的回收频率 -XX:NewRatio=3 # 栈帧大小为16m -Xss16m ##################老年代回收器############################ # 使用CMS老年代回收器 -XX:+UseConcMarkSweepGC # CMS的重新标记步骤:多线程一起执行 -XX:+CMSParallelRemarkEnabled # CMS的并发标记步骤:启用4个线程并发标记(理论上越多越好,前提是CPU核心足够多) -XX:ConcGCThreads=4 ##################JIT编译器############################ # 代码缓存,用于存放Just In Time编译后的本地代码,如果塞满,JVM将只解释执行,不再编译native代码。 -XX:ReservedCodeCacheSize=512m # 分层编译,JIT编译优化越来越好,IDEA运行时间越久越快 -XX:+TieredCompilation # 节省64位指针占用的空间,代价是JVM额外开销 -XX:+UseCompressedOops # 增大软引用在JVM中的存活时长(堆空闲空间越大越久) -XX:SoftRefLRUPolicyMSPerMB=50 -Dsun....

2019-10-25 · 1 min

SQL练习题

闲着没事情做几道SQL题。 Orcal SQL: 在线SQL测试 MySQL指定进入某个端口命令 mysql -uroot -p -P 3307 问题描述 1.学生表 Student(SID,Sname,Sage,Ssex) –SID 学生编号,Sname 学生姓名,Sage 出生年月,Ssex 学生性别. 2.课程表 Course(CID,Cname,TID) –CID –课程编号,Cname 课程名称,TID 教师编号. 3.教师表 Teacher(TID,Tname) –TID 教师编号,Tname 教师姓名. 4.成绩表 SC(SID,CID,score) –SID 学生编号,CID 课程编号,score 分数. 建表语句: create table Student(SID varchar(10),Sname nvarchar(10),Sage datetime,Ssex nvarchar(10)); insert into Student values('01' , '赵雷' , '1990-01-01' , '男'); insert into Student values('02' , '钱电' , '1990-12-21' , '男'); insert into Student values('03' , '孙风' , '1990-05-20' , '男'); insert into Student values('04' , '李云' , '1990-08-06' , '男'); insert into Student values('05' , '周梅' , '1991-12-01' , '女'); insert into Student values('06' , '吴兰' , '1992-03-01' , '女'); insert into Student values('07' , '郑竹' , '1989-07-01' , '女'); insert into Student values('08' , '王菊' , '1990-01-20' , '女'); create table Course(CID varchar(10),Cname nvarchar(10),TID varchar(10)); insert into Course values('01' , '语文' , '02'); insert into Course values('02' , '数学' , '01'); insert into Course values('03' , '英语' , '03'); create table Teacher(TID varchar(10),Tname nvarchar(10)); insert into Teacher values('01' , '张三'); insert into Teacher values('02' , '李四'); insert into Teacher values('03' , '王五'); create table SC(SID varchar(10),CID varchar(10),score decimal(18,1)); insert into SC values('01' , '01' , 80); insert into SC values('01' , '02' , 90); insert into SC values('01' , '03' , 99); insert into SC values('02' , '01' , 70); insert into SC values('02' , '02' , 60); insert into SC values('02' , '03' , 80); insert into SC values('03' , '01' , 80); insert into SC values('03' , '02' , 80); insert into SC values('03' , '03' , 80); insert into SC values('04' , '01' , 50); insert into SC values('04' , '02' , 30); insert into SC values('04' , '03' , 20); insert into SC values('05' , '01' , 76); insert into SC values('05' , '02' , 87); insert into SC values('06' , '01' , 31); insert into SC values('06' , '03' , 34); insert into SC values('07' , '02' , 89); insert into SC values('07' , '03' , 98); 题目 查询"01"课程比"02"课程成绩高的学生的信息及课程分数 查询同时存在"01"课程和"02"课程的情况 结果: +------+-------+---------------------+------+------------+------------+ | SID | Sname | Sage | Ssex | 01课程分数 | 02课程分数 | +------+-------+---------------------+------+------------+------------+ | 02 | 钱电 | 1990-12-21 00:00:00 | 男 | 70....

2019-10-15 · 11 min

Java线程检测死锁

死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。 Java线程中我们构造两个相互等待对方释放资源的线程就构成了死锁。 代码: public class DeadLockSimulation { private static String A = "a"; private static String B = "b"; public static void main(String[] args) { new DeadLockSimulation().deadLock(); } private void deadLock() { Thread t1 = new Thread(new Runnable() { @Override public void run() { synchronized (A) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (B) { System.out.println("t1"); } } } }); Thread t2 = new Thread(new Runnable() { @Override public void run() { synchronized (B) { synchronized (A) { System....

2019-08-10 · 2 min

Java两个线程之间共享数据

Java里面进行多线程通信的主要方式就是共享内存的方式,共享内存主要的关注点有两个:可见性和有序性原子性。 Java 内存模型(JMM)解决了可见性和有序性的问题,而锁解决了原子性的问题,理想情况下我们希望做到“同步”和“互斥”。 有以下常规实现方法: 一、数据抽象成一个类,对数据操作的方法封装在类里 public class MyData1 { private int j = 0; public static void main(String[] args) { MyData1 data = new MyData1(); AddRunnable addRunnable = new AddRunnable(data); DecRunnable decRunnable = new DecRunnable(data); new Thread(addRunnable).start(); new Thread(decRunnable).start(); } public synchronized void add() { j++; System.out.println("线程:" + Thread.currentThread().getName() + " j为:" + j); } public synchronized void dec() { j--; System.out.println("线程:" + Thread.currentThread().getName() + " j为:" + j); } public int getData() { return j; } } class AddRunnable implements Runnable { MyData1 data1 = new MyData1(); public AddRunnable(MyData1 data1) { this....

2019-07-01 · 2 min

Java基础复习(一)

Java基础 面向对象六原则一法则 单一职责原则(Single-Resposibility Principle) 一个类只做它该做的事情。(单一职责原则想表达的就是"高内聚",写代码最终极的原则只有六个字"高内聚、低耦合",所谓的高内聚就是一个代码模块只完成一项功能,在面向对象中,如果只让一个类完成它该做的事,而不涉及与它无关的领域就是践行了高内聚的原则,这个类就只有单一职责。另一个是模块化一个好的软件系统,它里面的每个功能模块也应该是可以轻易的拿到其他系统中使用的,这样才能实现软件复用的目标。)。 开放封闭原则(Open-Closed principle) 软件实体应当对扩展开放,对修改关闭。(在理想的状态下,当我们需要为一个软件系统增加新功能时,只需要从原来的系统派生出一些新类就可以,不需要修改原来的任何一行代码。要做到开闭有两个要点:1. 抽象是关键,一个系统中如果没有抽象类或接口系统就没有扩展点;2. 封装可变性,将系统中的各种可变因素封装到一个继承结构中,如果多个可变因素混杂在一起,系统将变得复杂而换乱,如果不清楚如何封装可变性) Liskov替换原则(Liskov-Substituion Principle) 里氏替换原则,任何时候都可以用子类型替换掉父类型。(关于里氏替换原则的描述,Barbara Liskov女士的描述比这个要复杂得多,但简单的说就是能用父类型的地方就一定能使用子类型。里氏替换原则可以检查继承关系是否合理,如果一个继承关系违背了里氏替换原则,那么这个继承关系一定是错误的,需要对代码进行重构。例如让猫继承狗,或者狗继承猫,又或者让正方形继承长方形都是错误的继承关系,因为你很容易找到违反里氏替换原则的场景。需要注意的是:子类一定是增加父类的能力而不是减少父类的能力,因为子类比父类的能力更多,把能力多的对象当成能力少的对象来用当然没有任何问题。)代表约定、代表角色,能否正确的使用接口一定是编程水平高低的重要标识。) 依赖倒置原则(Dependecy-Inversion Principle) 面向接口编程。(该原则说得直白和具体一些就是声明方法的参数类型、方法的返回类型、变量的引用类型时,尽可能使用抽象类型而不用具体类型,因为抽象类型可以被它的任何一个子类型所替代,请参考下面的里氏替换原则。) 接口隔离原则(Interface-Segregation Principle) 接口要小而专,绝不能大而全。(臃肿的接口是对接口的污染,既然接口表示能力,那么一个接口只应该描述一种能力,接口也应该是高度内聚的。例如,琴棋书画就应该分别设计为四个接口,而不应设计成一个接口中的四个方法,因为如果设计成一个接口中的四个方法,那么这个接口很难用,毕竟琴棋书画四样都精通的人还是少数,而如果设计成四个接口,会几项就实现几个接口,这样的话每个接口被复用的可能性是很高的。Java中的接口代表能力、 分离的手段主要有以下两种:1. 委托分离,通过增加一个新的类型来委托客户的请求,隔离客户和接口的直接依赖,但是会增加系统的开销。2. 多重继承分离,通过接口多继承来实现客户的需求,这种方式是较好的。 合成聚合复用原则 优先使用聚合或合成关系复用代码。(通过继承来复用代码是面向对象程序设计中被滥用得最多的东西,因为所有的教科书都无一例外的对继承进行了鼓吹从而误导了初学者,类与类之间简单的说有三种关系,Is-A关系、Has-A关系、Use-A关系,分别代表继承、关联和依赖。其中,关联关系根据其关联的强度又可以进一步划分为关联、聚合和合成,但说白了都是Has-A关系,合成聚合复用原则想表达的是优先考虑Has-A关系而不是Is-A关系复用代码,原因嘛可以自己从百度上找到一万个理由,需要说明的是,即使在Java的API中也有不少滥用继承的例子,例如Properties类继承了Hashtable类,Stack类继承了Vector类,这些继承明显就是错误的,更好的做法是在Properties类中放置一个Hashtable类型的成员并且将其键和值都设置为字符串来存储数据,而Stack类的设计也应该是在Stack类中放一个Vector对象来存储数据。记住:任何时候都不要继承工具类,工具是可以拥有并可以使用的,而不是拿来继承的。) 迪米特法则 迪米特法则又叫最少知识原则,一个对象应当对其他对象有尽可能少的了解。再复杂的系统都可以为用户提供一个简单的门面,Java Web开发中作为前端控制器的Servlet或Filter不就是一个门面吗,浏览器对服务器的运作方式一无所知,但是通过前端控制器就能够根据你的请求得到相应的服务。调停者模式也可以举一个简单的例子来说明,例如一台计算机,CPU、内存、硬盘、显卡、声卡各种设备需要相互配合才能很好的工作,但是如果这些东西都直接连接到一起,计算机的布线将异常复杂,在这种情况下,主板作为一个调停者的身份出现,它将各个设备连接在一起而不需要每个设备之间直接交换数据,这样就减小了系统的耦合度和复杂度。 Java如何实现的平台无关 Java语言规范 通过规定Java语言中基本数据类型的取值范围和行为 Class文件 所有Java文件要编译成统一的Class文件 Java虚拟机 通过Java虚拟机将Class文件转成对应平台的二进制文件等 JVM支持哪些语言(Kotlin、Groovy、JRuby、Jython、Scala) 值传递、引用传递 Java中只有值传递 public class Main { public static void main(String[] args) { int a = 10; Integer b = 20; int[] arr = {1, 2}; swap(a, b); System.out.println(String.format("a:%d b:%d", a, b)); swap(arr); System.out.println(Arrays.toString(arr)); } // 对于对象而言传递的是对象引用的地址作为值 static void swap(int a, Integer b) { int t = a; a = b; b = t; } static void swap(int[] arr) { arr[0] = 996; } } /** OutPut: a:10 b:20 [996, 2] **/ 值传递(pass by value)是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。 引用传递(pass by reference)是指在调用函数时将实际参数的地址直接传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。 成员变量和方法作用域 作用域 当前类 同package 子孙类 不同package public √ √ √ √ protected √ √ √ × fridendly(默认) √ √ × × private √ × × × 例子:protected在其子类中可以访问,无论是子类内部还是子类的实例,无论它们是在哪个包中, 但如果子类与父类不在同一个包中,在子类中用父类的实例去访问的话不可以。...

2019-05-01 · 3 min

设计模式复习

设计模式复习 23种设计模式主要分为三类:创建型模式、结构型模式、行为型模式。 创建型模式 单例模式 实现单例模式的思路是:一个类能返回对象一个引用(永远是同一个)和一个获得该实例的方法(必须是静态方法,通常使用getInstance这个名称);当我们调用这个方法时,如果类持有的引用不为空就返回这个引用,如果类保持的引用为空就创建该类的实例并将实例的引用赋予该类保持的引用;同时我们还将该类的构造函数定义为私有方法,这样其他处的代码就无法通过调用该类的构造函数来实例化该类的对象,只有通过该类提供的静态方法来得到该类的唯一实例。 代码实现 饿汉式 线程安全 class Singleton { private static Singleton instance = new Singleton(); private Singleton() {} public static Singleton getInstance() { return instance; } } 懒汉式 双向检查锁定 class Singleton { // volatile 多线程安全, 但屏蔽Java虚拟机优化, 效率降低 private volatile static Singleton instance = null; private Singleton() {} public static Singleton getInstance() { if (instance == null) { // 锁定代码块 synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } } 使用静态内部类实现 // IoDH 初始化不会失败使用, 延迟加载 public class Singleton { private static class SingletonHolder { private static final Singleton instance = new Singleton(); } public static Singleton getInstance(){ return SingletonHolder....

2019-04-01 · 2 min

常见排序算法实现

排序比较 快速排序 /** * 快速排序算法 */ public static void quickSort(int[] list, int left, int right) { if (left < right) { // 分割数组,找到分割点 int point = partition(list, left, right); // 递归调用,对左子数组进行快速排序 quickSort(list, left, point - 1); // 递归调用,对右子数组进行快速排序 quickSort(list, point + 1, right); } } /** * 分割数组,找到分割点 */ public static int partition(int[] list, int left, int right) { // 用数组的第一个元素作为基准数 int first = list[left]; while (left < right) { while (left < right && list[right] >= first) { right--; } // 交换 swap(list, left, right); while (left < right && list[left] <= first) { left++; } // 交换 swap(list, left, right); } // 返回分割点所在的位置 return left; } /** * 交换数组中两个位置的元素 */ public static void swap(int[] list, int left, int right) { int temp; if (list !...

2019-02-20 · 4 min

问卷星自动提交脚本

思路 分析页面结构, 问题标号: q+第几题, 问题选项: q+第几题+_第几个选项. 对一次提交进行抓包, 抓取post数据包. 对submidata进行解码得到如下. 明显看出是题号$选项号}组成的. 写python脚本构造post请求.利用X-Forwarded-For绕过服务器IP地址过滤. import requests from time import * from random import randint for i in range(10): header = { 'Host': 'www.wjx.cn', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:63.0) Gecko/20100101 Firefox/63.0', 'X-Forwarded-For': str(randint(1, 255)) + '.' + str(randint(1, 255)) + '.' + str(randint(1, 255)) + '.' + str( randint(1, 255)), 'Referer': 'https://www.wjx.cn###.aspx', 'Cookie': 'acw_tc=2f624a1f154##', } print("第 " + str(i) + " 提交" + " Using IP:" + header['X-Forwarded-For'] + ' to compalte this Q....

2019-01-01 · 1 min

Manacher算法-最长回文串

题目 求解字符串最长回文串。 leetcode: 最长回文子串 样例 Input 121 1 daccbba bb Output 121 1 accbba bb Manacher算法,时间复杂度O(n), 空间复杂度O(1)。 步骤 先对s串处理转换为奇数长度的串。 s = "12212321" ==> S # 1 # 2 # 2 # 1 # 2 # 3 # 2 # 1 # P 1 2 1 2 5 2 1 4 1 2 1 6 1 2 1 2 1 p[i]表示记录以字符S[i]为中心的最长回文子串向左或向右扩张的长度(包括S[i])。 即以i为原点的最大回文半径。 Manacher算法增加两个辅助变量id和mx。 id代表当前“已经匹配完毕的结尾最远的回文串”中心为s的第ID位。 mx = p[i] + id代表当前“已经匹配完毕的结尾最远的回文串”到达了s的第Mx位。 最长回文子串长度 = p[i] - 1 = 5。...

2018-11-15 · 2 min