回顾 -------------- 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] 程序计数器,累计程序指令