apt.sh更新清理软件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
sudo aptitude update
sudo aptitude upgrade -y
sudo aptitude autoclean -y
sudo aptitude clean

echo "\033[31m aptitude end \033[0m"

sudo apt-get update
sudo apt-get upgrade -y
sudo apt-get autoremove -y
sudo apt-get autoclean
sudo apt-get clean

echo "\033[31m apt-get end \033[0m"

ls.sh查看deb包缓存

1
2
3
4
cd /var/cache/apt/archives
pwd
echo "==================="
ls | grep deb

非pom导入的额外Jar包, 在 maven clean install 的时候是会报错的, 程序包 *.*.* 不存在, 需要配置 pom.xml

我们将额外Jar包放在一个统一的目录 ${dirs} 下面。

dependency 加上 <scope>system</scope> 以及 Jar包位置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<dependency>
<groupId>${groupId}</groupId>
<artifactId>${artifactId}</artifactId>
<version>${version}</version>
<scope>system</scope>
<systemPath>${project.basedir}/${dirs}/target1.jar</systemPath>
</dependency>

<dependency>
<groupId>${groupId}</groupId>
<artifactId>${artifactId}</artifactId>
<version>${version}</version>
<scope>system</scope>
<systemPath>${project.basedir}/${dirs}/target2.jar</systemPath>
</dependency>
阅读全文 »

npm使用淘宝源

1
npm config set registry https://registry.npmmirror.com/

.npmrc

1
2
3
registry=https://registry.npmmirror.com/
sass_binary_site=https://npm.taobao.org/mirrors/node-sass/
electron_mirror=https://npm.taobao.org/mirrors/electron/

使用cnpm

1
npm install -g cnpm@6.2.0 --registry=https://registry.npmmirror.com

.yarnrc

1
2
3
4
5
6
7
8
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


registry "https://registry.npmmirror.com/"
electron_mirror "https://npm.taobao.org/mirrors/electron/"
lastUpdateCheck 1692882092809
sass_binary_site "https://npm.taobao.org/mirrors/node-sass/"

使用nvm管理node版本

1
2
3
4
5
# 列出node版本
nvm ls

#切换node版本
nvm use 16.20.1

Fixing npm permissions

1
sudo chown -R $(whoami) $(npm config get prefix)/{lib/node_modules,bin,share}

This changes the permissions of the sub-folders used by npm and some other tools (lib/node_modules, bin, and share).

什么是 CAS

CAS, Compare and Swap 即比较并替换, CAS 有三个操作数:内存值 V、旧的预期值 A、要修改的值 B, 当且仅当预期值 A 和内存值 V 相同时, 将内存值修改为 B 并返回 true, 否则什么都不做并返回 false。

java.util.concurrent.atomic 包下的原子操作类都是基于 CAS 实现的, 接下去我们通过 AtomicInteger 来看看是如何通过 CAS 实现原子操作的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class AtomicInteger extends Number implements java.io.Serializable {
// setup to use Unsafe.compareAndSwapInt for updates
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;

static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}

private volatile int value;
public final int get() {return value;}
}
  1. Unsafe 是 CAS 的核心类, Java 无法直接访问底层操作系统, 而是通过本地(native)方法来访问。不过尽管如此, JVM 还是开了一个后门, JDK 中有一个类 Unsafe, 它提供了硬件级别的原子操作。

  2. valueOffset 表示的是变量值在内存中的偏移地址, 因为 Unsafe 就是根据内存偏移地址获取数据的原值的。

  3. value 是用 volatile 修饰的, 保证了多线程之间看到的 value 值是同一份。

阅读全文 »

说明

sychronized 一般用来修饰一个方法或者一个代码块。利用 sychronized 实现同步的基础:java 中每一个对象都可以作为锁。具体表现为以下 3 中形式。

  1. 修饰一个代码块, 被修饰的代码块称为同步语句块, 其作用的范围是大括号{}括起来的代码, 作用的对象是调用这个代码块的对象;

  2. 修饰一个方法, 被修饰的方法称为同步方法, 其作用的范围是整个方法, 作用的对象是调用这个方法的对象;

  3. 修改一个静态的方法, 其作用的范围是整个静态方法, 作用的对象是这个类的所有对象;

  4. 修改一个类, 其作用的范围是synchronized后面括号括起来的部分, 作用主的对象是这个类的所有对象。

一个线程访问一个对象的synchronized代码块时, 别的线程可以访问该对象的非synchronized代码块而不受阻塞。

总结

  1. 无论synchronized关键字加在方法上还是对象上, 如果它作用的对象是非静态的, 则它取得的锁是对象;如果synchronized作用的对象是一个静态方法或一个类, 则它取得的锁是对类, 该类所有的对象同一把锁。

  2. 每个对象只有一个锁(lock)与之相关联, 谁拿到这个锁谁就可以运行它所控制的那段代码。

  3. 实现同步是要很大的系统开销作为代价的, 甚至可能造成死锁, 所以尽量避免无谓的同步控制。

锁的可重入性

先举例来说明锁的可重入性:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class UnReentrant{
Lock lock = new Lock();
public void outer(){
lock.lock();
inner();
lock.unlock();
}
public void inner(){
lock.lock();
//do something
lock.unlock();
}
}

outer 中调用了 inner, outer 先锁住了 lock, 这样 inner 就不能再获取 lock。其实调用 outer 的线程已经获取了 lock 锁, 但是不能在 inner 中重复利用已经获取的锁资源, 这种锁即称之为 不可重入 。通常也称为 自旋锁 。相对来说, 可重入就意味着:线程可以进入任何一个它已经拥有的锁所同步着的代码块。

ReentrantLock 相比 synchronized 有如下几个优势

  1. 可以反复进入, 同一个线程获得几个锁, 在释放的时候也需要同等释放, 要不然会死锁的(其实 synchronized 也是可重入的);

  2. 支持锁中断 lockInterruptiblity(), 防死锁, 优先响应中断;

  3. 支持限时获取锁, lock.tryLock(int,TimeUnit); 在给定的时间范围捏尝试获取锁;

  4. 支持尝试获取锁, tryLock 不带参数, 如果获取不到则立刻返回 false, 而不等待锁;

  5. 公平锁 ReentrantLock(boolean fair), 排队获取锁, 性能相对低下;

  6. 配合 Condition, 可以让线程在合适的时间等待, 得到通知后继续执行。

类的加载

其中类加载的过程包括了加载、验证、准备、解析、初始化、使用、卸载七个阶段。验证、准备、解析三个阶段统称为连接。

在这七个阶段中, 加载、验证、准备和初始化和卸载这五个阶段发生的顺序是确定的, 而解析阶段则不一定, 它在某些情况下可以在初始化阶段之后开始, 这是为了支持 Java 语言的运行时绑定(也成为动态绑定或晚期绑定)。另外注意这里的几个阶段是按顺序开始, 而不是按顺序进行或完成, 因为这些阶段通常都是互相交叉地混合进行的, 通常在一个阶段执行的过程中调用或激活另一个阶段。

加载

加载时类加载过程的第一个阶段, 在加载阶段, 虚拟机需要完成以下三件事情:

  1. 通过一个类的全限定名来获取其定义的二进制字节流。
  2. 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
  3. 在 Java 堆中生成一个代表这个类的 java.lang.Class 对象, 作为对方法区中这些数据的访问入口。

类加载器中将详细描述使用类加载器加载类的过程

阅读全文 »

JDK 命令行的工具

JPS :虚拟机进程状况工具

-q 只输出 LVMID, 省略主类的名称。
-m 输出虚拟机进程启动时传递给主类 main() 函数的参数。
-l 输出主类的全名, 如果进程执行的是 Jar 包, 输出 Jar 路径。
-v 输出虚拟机进程启动 JVM 参数。

jstat:虚拟机统计信息监视工具

可以显示本地或远程虚拟机进程中的类装载、内存、垃圾收集、JIT 编译等运行数据。
命令格式 jstat [option vmid [interval[s|ms] [count]]]
如果是远程虚拟机进程 那么 VMID 格式:[protocol:][//]lvmid[@hostname[:port]/servername]
参数 interval 和 count 代表查询间隔和次数, 如果省略了这两个参数, 说明只查询一次。

阅读全文 »

垃圾收集器

可达性分析算法

通过一系列的称谓 GC Roots 的对象作为起始点, 从这些节点开始向下搜索, 搜索所有走过的路径为引用链, 当一个对象到 GC Roots 没有任何引用链项链时, 则证明此对象时不可用的。

Java 语言中, 可作为 GC Roots 的对象包括下面几种:

  1. 虚拟机栈 (栈帧中的本地变量表) 中引用的对象
  2. 方法区中类静态属性引用的对象
  3. 方法区中常量引用的对象
  4. 本地方法栈中 JNI(即一般说的 Native 方法) 引用的对象

引用类型

从 JDK1.2 之后, Java 对引用的概念进行了扩充, 将引用分为强引用, 软引用, 弱引用, 虚引用, 这四种引用的强度一次逐渐减弱。

  1. 强引用就是指在程序代码之中普遍存在的, 类似 “Object obj = new Object()” 这类的引用, 只要强引用还存在, 垃圾回收器永远不会回收掉被引用的对象。
  2. 软引用是用来描述一些还有用但并非需要的对象, 对于软引用关联着的对象, 在系统将要发生内存异常之前, 将会把这些对象列进回收范围之中进行第二次回收, 如果这次回收还没有足够的内存, 才会抛出内存异常。
  3. 弱引用也是用来描述非必需对象的, 但是它的强度比软引用更弱一些, 被弱引用关联的对象只能生存岛下一次垃圾收集发生之前, 当垃圾收集器工作时, 无论当前内存释放足够, 都会回收掉只被弱引用关联的对象。
  4. 虚引用也称为幽灵引用或者幻影引用, 它是最弱的一种引用关系, 一个对象是否有虚引用的存在, 完全不会对其生存时间构成影响, 也无法通过虚引用来取得一个对象实例, 对一个对象设置虚引用关联的唯一目的就是能在这个对象被收集器回收时收到一个系统通知。
阅读全文 »

运行时数据区域

运行时数据区域

程序计数器

字节码解释器通过更改这个计数器的值来选取下一条需要执行的字节码指令。每条线程都需要一个独立的程序计数器, 线程之间, 互不影响。Java虚拟机规范中唯一一个没有规定任何OutOfMemoryError情况的区域

阅读全文 »
0%