Ubuntu apt 更新和清理
apt.sh
更新清理软件
1 | sudo aptitude update |
ls.sh
查看deb包缓存
1 | cd /var/cache/apt/archives |
apt.sh
更新清理软件1 | sudo aptitude update |
ls.sh
查看deb包缓存1 | cd /var/cache/apt/archives |
非pom导入的额外Jar包, 在 maven clean install
的时候是会报错的, 程序包 *.*.* 不存在
, 需要配置 pom.xml
。
我们将额外Jar包放在一个统一的目录
${dirs}
下面。
dependency
加上 <scope>system</scope>
以及 Jar包位置
1 | <dependency> |
1 | npm config set registry https://registry.npmmirror.com/ |
1 | registry=https://registry.npmmirror.com/ |
1 | npm install -g cnpm@6.2.0 --registry=https://registry.npmmirror.com |
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. |
1 | # 列出node版本 |
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
, Compare and Swap
即比较并替换, CAS 有三个操作数:内存值 V、旧的预期值 A、要修改的值 B, 当且仅当预期值 A 和内存值 V 相同时, 将内存值修改为 B 并返回 true, 否则什么都不做并返回 false。
java.util.concurrent.atomic 包下的原子操作类都是基于 CAS 实现的, 接下去我们通过 AtomicInteger 来看看是如何通过 CAS 实现原子操作的:
1 | public class AtomicInteger extends Number implements java.io.Serializable { |
Unsafe 是 CAS 的核心类, Java 无法直接访问底层操作系统, 而是通过本地(native)方法来访问。不过尽管如此, JVM 还是开了一个后门, JDK 中有一个类 Unsafe, 它提供了硬件级别的原子操作。
valueOffset 表示的是变量值在内存中的偏移地址, 因为 Unsafe 就是根据内存偏移地址获取数据的原值的。
value 是用 volatile 修饰的, 保证了多线程之间看到的 value 值是同一份。
sychronized 一般用来修饰一个方法或者一个代码块。利用 sychronized 实现同步的基础:java 中每一个对象都可以作为锁。具体表现为以下 3 中形式。
修饰一个代码块, 被修饰的代码块称为同步语句块, 其作用的范围是大括号{}括起来的代码, 作用的对象是调用这个代码块的对象;
修饰一个方法, 被修饰的方法称为同步方法, 其作用的范围是整个方法, 作用的对象是调用这个方法的对象;
修改一个静态的方法, 其作用的范围是整个静态方法, 作用的对象是这个类的所有对象;
修改一个类, 其作用的范围是synchronized后面括号括起来的部分, 作用主的对象是这个类的所有对象。
一个线程访问一个对象的synchronized代码块时, 别的线程可以访问该对象的非synchronized代码块而不受阻塞。
无论synchronized关键字加在方法上还是对象上, 如果它作用的对象是非静态的, 则它取得的锁是对象;如果synchronized作用的对象是一个静态方法或一个类, 则它取得的锁是对类, 该类所有的对象同一把锁。
每个对象只有一个锁(lock)与之相关联, 谁拿到这个锁谁就可以运行它所控制的那段代码。
实现同步是要很大的系统开销作为代价的, 甚至可能造成死锁, 所以尽量避免无谓的同步控制。
先举例来说明锁的可重入性:
1 | public class UnReentrant{ |
outer 中调用了 inner, outer 先锁住了 lock, 这样 inner 就不能再获取 lock。其实调用 outer 的线程已经获取了 lock 锁, 但是不能在 inner 中重复利用已经获取的锁资源, 这种锁即称之为 不可重入
。通常也称为 自旋锁
。相对来说, 可重入就意味着:线程可以进入任何一个它已经拥有的锁所同步着的代码块。
可以反复进入, 同一个线程获得几个锁, 在释放的时候也需要同等释放, 要不然会死锁的(其实 synchronized 也是可重入的);
支持锁中断 lockInterruptiblity(), 防死锁, 优先响应中断;
支持限时获取锁, lock.tryLock(int,TimeUnit); 在给定的时间范围捏尝试获取锁;
支持尝试获取锁, tryLock 不带参数, 如果获取不到则立刻返回 false, 而不等待锁;
公平锁 ReentrantLock(boolean fair), 排队获取锁, 性能相对低下;
配合 Condition, 可以让线程在合适的时间等待, 得到通知后继续执行。
其中类加载的过程包括了加载、验证、准备、解析、初始化、使用、卸载七个阶段。验证、准备、解析三个阶段统称为连接。
在这七个阶段中, 加载、验证、准备和初始化和卸载这五个阶段发生的顺序是确定的, 而解析阶段则不一定, 它在某些情况下可以在初始化阶段之后开始, 这是为了支持 Java 语言的运行时绑定(也成为动态绑定或晚期绑定)。另外注意这里的几个阶段是按顺序开始, 而不是按顺序进行或完成, 因为这些阶段通常都是互相交叉地混合进行的, 通常在一个阶段执行的过程中调用或激活另一个阶段。
加载时类加载过程的第一个阶段, 在加载阶段, 虚拟机需要完成以下三件事情:
在类加载器中将详细描述使用类加载器加载类的过程
-q 只输出 LVMID, 省略主类的名称。
-m 输出虚拟机进程启动时传递给主类 main() 函数的参数。
-l 输出主类的全名, 如果进程执行的是 Jar 包, 输出 Jar 路径。
-v 输出虚拟机进程启动 JVM 参数。
可以显示本地或远程虚拟机进程中的类装载、内存、垃圾收集、JIT 编译等运行数据。
命令格式 jstat [option vmid [interval[s|ms] [count]]]
如果是远程虚拟机进程 那么 VMID 格式:[protocol:][//]lvmid[@hostname[:port]/servername]
参数 interval 和 count 代表查询间隔和次数, 如果省略了这两个参数, 说明只查询一次。
通过一系列的称谓 GC Roots
的对象作为起始点, 从这些节点开始向下搜索, 搜索所有走过的路径为引用链, 当一个对象到 GC Roots 没有任何引用链项链时, 则证明此对象时不可用的。
Java 语言中, 可作为 GC Roots 的对象包括下面几种:
从 JDK1.2 之后, Java 对引用的概念进行了扩充, 将引用分为强引用, 软引用, 弱引用, 虚引用, 这四种引用的强度一次逐渐减弱。