回顾
--------------
1、并发库下的重入锁
相较于synchronized来讲,cpu资源消耗少。粒度更细,可以控制到共享读锁和
独占写锁,底层实现Unsafe对数字的控制实现,这些数字控制都是原子量实现。
原子量底层控制实现原理是CAS(CompareAndSwap,比较并交换,反复尝试的过程,
而不是将cpu阻塞)。tryLock()尝试上锁,如果得不到,即刻返回。
java.util.concurrent.ReentrantLock //可重入锁
java.util.concurrent.ReentrantReadWriteLock //可重入读写锁
java.util.concurrent.Executors //执行
java.util.concurrent.ThreadPoolExector //线程池
java.util.concurrent.AtomicInteger //原子量
java.util.concurrent.BlockingQueue //List
java.util.concurrent.ConcurrentMap //Map
2、反射
Class
Method
Field
Constructor
3、内省
Introspector
BeanInfo
PropertyDescriptor
4、代理
Proxy
接口集合
目标对象
InvocationHandler
JVM
----------------
Java virtual machine.sand box,沙箱。
[Runtime data area]
运行时数据区,
[method area]
方法区, 被所有线程共享,存放的类的信息,如果出现并发加载
类的时候,只有一个classloader进行加载,其他的等待。
[heap]
堆,被所有线程共享,存放的是对象和数组。
堆内部划分成年轻代和年老代。
年轻代内部划分成伊甸区和幸存区。
幸存区又划分成幸存一区和幸存二区。
堆
|----年青代
|----伊甸区
|----幸存区(两个幸存区的目的是为了进行内存碎片整理。)
|----幸存一区
|----幸存二区
|----年老代(至少保留512K空间)
对象回收流程是从伊甸区创建,依次经过幸存一区(二区),
到幸存二区(一区),最后达到年老代。
java.lang.OutOfMemoryError: Java heap space,堆溢出
//调整堆空间大小 , mx:最大值 ms:初始值
java -Xmx4g -Xms4g
使用jvisualvm考察jvm的内部结构。
cmd -> jvisualvm ->工具 -> 插件 -> visual GC -> 安装.
-Xms1g //堆初始大小
-Xmx1g //堆最大值
-Xmn1g //年轻代大小
-XX:NewSize=1g //年轻代初始值
-XX:MaxNewSize=1g //年轻代最大值
-XX:NewRatio=1 //设置年老代和年轻的倍数(比率),默认是2.
-XX:SurvivorRatio=1 //设置伊甸区和单个幸存区的比率,默认值是6
//调整堆空间
java -Xmx500m -Xms500m -Xmn500m //ok
java -Xmx500m -Xms500m -Xmn0m //not ok,年轻代至少 > 1.5m
java -Xms1g -Xmx1g -XX:NewSize=750m -XX:MaxNewSize=750m -XX:SurvivorRatio=1
[垃圾回收]
对象被回收的条件是没有任意引用能够直接或间接到达该对象。
full gc //发生在old代gc。
minor gc //发生在young代。
[通过jconsole软件考察内存结构]
cmd -> jconsole
[从堆角度对内存进行换分]
1、堆内内存,年老代 + 年轻代
2、非堆内存(non-heap),JVM - 堆,栈空间,方法区。
metaspace(1.8改名,对应的是方法区) + 代码缓存区 + 压缩类空间。
3、离堆内存(off-heap),JVM之外内存。
在操作系统的内存中,但不在jvm中,java称之为直接访问。
public static void main(String[] args) {
//直接内存
for(;;){
DirectBuffer buf = (DirectBuffer) ByteBuffer.allocateDirect(1024 * 1024 * 500);
buf.cleaner().clean();
//错误,因为离堆内存已经被回收掉了。
int n = ((ByteBuffer)buf).get(0);
System.out.println(n);
System.gc();
}
}
[java stack]
java栈
先进后出
对应一个线程,一个应用程序至少有一个栈,即主线程对应的栈(主栈).
栈的操作有压栈(push)和弹栈(pop)。
java栈中压入的stack frame,也叫方法帧(method frame).
死递归容易导致栈溢出,可以通过jvm参数来进行设置。
默认是1m。
//调整栈空间
java -Xss1m
[native method stack]
本地方法栈,
[program counter register]
程序计数器,累计程序指令