21. Java的虚拟机的内容。这部分主要包括三部分,GC、类加载机制,以及内存?

时间:2023-01-03 12:30:10
第一:GC相关内容
①什么时候一个对象会被GC?
这里让我想到了,组成原理中内存的一部分内容,就是内存命中率的问题。在虚拟机存储器中,当内存不够的时候,会引用外部存储器中的存储介质。然后如果一个内存经常被访问到或者在预计的时间内会被访问到。那么就会判定该地址的命中率很高。反言之,那么就会被回收了。一段内存在预计的时间内无法被其他对象引用或者已经没有其他的对象应用该段内存。也不是说被gc判定为垃圾的时候就会立马被回收。因为可能过一段时间后还是会被引用到。 那么问题就来了,什么时候会被全部回收,什么时候不会被回收。
②为什么这个时候对象会被GC?
由于对象进行了分代处理,因此垃圾回收区域,时间也不一样。gc有两种类型:scavenge GC和FullGC
③GC策略有那些分类?
第二:类加载机制 类加载机制是否和程序装在方式相同(组成原理中的内容)?
①类加载器都有哪些?
根加载器(启动类加载器BookStrapClassLoader),扩展加载器(Extension ClassLoader),系统加载器(App ClassLoader),自定义加载器(ClassLoader);
还有一种说法:一种是系统自带的,另外一种是用户自己编写的。系统自带的是前三种,自定义的是用户编写的
②每一个加载器都有哪些类?
③这些类加载的父子关系?
如果一个类加载器收到了一个类的加载请求,它不会自己去尝试加载一个类,而是把这个请求转交给父类加载去去完成。每一个层次的类都是如此,因此所有的类加载请求都应该传递到最顶层的启动类加载器中,只有父类加载器无法完成这个请求加载的时候(在他的范围内没有搜索到这个类时候)子类才会去自己加载。双亲委派的好处就是避免有些类重复加载
系统类的加载器的父加载器必须是扩展加载器,而扩展加载器的父加载器必须是引导类加载器。
表 1. ClassLoader 中与加载类相关的方法
方法 说明
getParent() 返回该类加载器的父类加载器。
loadClass(String name) 加载名称为 name的类,返回的结果是 java.lang.Class类的实例。
findClass(String name) 查找名称为 name的类,返回的结果是 java.lang.Class类的实例。
findLoadedClass(String name) 查找名称为 name的已经被加载过的类,返回的结果是 java.lang.Class类的实例。
defineClass(String name, byte[] b, int off, int len) 把字节数组 b中的内容转换成 Java 类,返回的结果是 java.lang.Class类的实例。这个方法被声明为 final的。
resolveClass(Class<?> c) 链接指定的 Java 类。

第三:内存
①内存分为哪几个部分?
Java中的内存被分成四部分:代码区,栈区,堆区,静态区域
栈区:由编译器自动分配,存放函数参数值,局部变量等;具体方法执行结束后,系统自动释放JVN内存资源
堆区:一般由程序员分配释放,存放New分配的对象和数组,jvm不定时查看这个对象,如果没有引用指向这个对象就回收
静态区:存放全局变量,静态变量和字符常量,不释放
代码区:存放程序中的二进制代码,而且是多个对象共享一个代码区域。
②这些部分分别存储哪些数据?
栈区
---------------------------------
基础数据类型 byte short int long float double char boolean
方法的形式参数,方法调用完后从栈空间回收
引用对象的地址,引用完后,栈空间地址立即被回收,堆空间等待GC
栈内的数据线程之间独立
具体划分为:基本类型变量区、执行环境上下文、操作指令区

堆区
---------------------------------
this
new 出来的对象
数组
jvm只有一个堆区,并被所有线程共享

方法区(又叫静态区和永久区)
---------------------------------
字符串常量
static
所有class
被所有线程共享, 其内存放程序中永远唯一的元素
③一个对象在从创建到销毁怎么在这些部分中存活或者转移的?
④内存的哪些部分会被GC回收?
当Java虚拟机的加载器不同的时候,即使加载同一个名字的class对象,那么加载出来的字节码也是不同的。就好像同一段文字,被不同地区人去读取,都会读出不同的方言的味道一样。