本地方法
使用native修饰的方法是本地方法,不能和abstract放在一起。
因为native的意思是调用本地方法,非java的方法,虽然看起来没有方法体,但是存在方法实现
而abstract是指抽象方法,是java层面的,它修饰的方法不能有方法体,必须由它的子类重写
本地方法栈
堆
一个JVM实例就是一个进程,
运行一个java程序,也就是把编译产生的class文件放到JVM实例中执行,一个JVM实例就对应一个进程。
一个JVM实例中只会存在一个堆空间和方法区,所以是线程共享的
在堆中并不都是线程共享的,还有一块线程私有的缓冲区(TLAB)
如果堆空间都是共享区域,那么并发性就会变差,所以在堆中又分出一个小空间TLAB,这样并发性更好
栈中不存储对象和数组(不考虑逃逸事件),栈中只保存引用,引用指向对象或者数组在堆中位置,而具体的方法结构是保存在方法区的
当变量引用从栈中弹出后,堆中存储的实例虽然失去引用,但是不会立马被回收,而是要等GC去回收
为什么不立马回收呢?
GC是守护线程,main是用户线程,当GC执行的时候会出现stop the world的情况,也就是用户线程要停止执行,所以如果立马GC,会导致用户线程一直停顿,那么影响程序执行。
查看字节码文件,可知,new 用来创建对象,newarray用来创建数组,这两个操作一出现,意味着在堆空间分配空间,创建对象或者数组。
这在java源文件中只是一个new字完成的。
GC的主要区域就是堆,如果是对大内存或者需要频繁GC,那么就要考虑JVM调优的问题
堆的内存细分
讲新生代、年轻代都是一个意思,老年代、老年区也是一个意思
JDK7和JDK8的一个区别就是JDK8中使用源空间来替换了永久代,
不管是7还是8,堆空间逻辑上包含的是有永久代或者源空间,但是实际上永久代或源空间时方法区的一个落地实现,是不属于堆空间管理的。
堆空间大小的设置
、
开发中一般会把堆内存大小的初始值和最大值设置成相同的,因为如果初始堆小的话,在堆内存不足的时候会扩容,而当GC的时候又会出现销毁扩容的内存,这样会导致系统出现不必要的压力,所以都设置相同。
jps查看当前运行的进程,
jstat -gc pid 查看运行进程的内存使用情况
设置编译时环境和运行时环境
编译时环境
运行时环境
针对的是当前project下的某module的class文件
关于异常的问题
Throwable下包括Error和Exception
狭义上的异常就是指Exception,比如IOException等。
广义上异常,程序的不正常就是异常,这其实就是对应于Throwable,所以可以答StackOverflowError栈溢出和OutOfMemoryError内存溢出等