java中的Person是什么

发布时间:2021-09-14 13:58:37 作者:柒染
来源:亿速云 阅读:263

这篇文章将为大家详细讲解有关java中的Person是什么,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

方法区

这次所讲述的是运行时数据区的最后一个部分

java中的Person是什么

从线程共享与否的角度来看

java中的Person是什么

ThreadLocal:如何保证多个线程在并发环境下的安全性?典型应用就是数据库连接管理,以及会话管理

一 栈、堆、方法区的交互关系

下面就涉及了对象的访问定位

java中的Person是什么

二 方法区的理解

《Java虚拟机规范》中明确说明:“尽管所有的方法区在逻辑上是属于堆的一部分,但一些简单的实现可能不会选择去进行垃圾收集或者进行压缩。”但对于HotSpotJVM而言,方法区还有一个别名叫做Non-Heap(非堆),目的就是要和堆分开。

所以,方法区看作是一块独立于Java堆的内存空间。

java中的Person是什么

方法区主要存放的是 Class,而堆中主要存放的是 实例化的对象

HotSpot中方法区的演进

现在来看,当年使用永久代,不是好的idea。导致Java程序更容易oom(超过-XX:MaxPermsize上限)

java中的Person是什么

    java中的Person是什么

三 设置方法区大小与OOM

JKD7 及以前

java中的Person是什么

JDK8以后

如何解决这些OOM

四 方法区的内部结构

java中的Person是什么

《深入理解Java虚拟机》书中对方法区(Method Area)存储内容描述如下:它用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等。

java中的Person是什么

类型信息

对每个加载的类型(类class、接口interface、枚举enum、注解annotation),JVM必须在方法区中存储以下类型信息:

  1. 这个类型的完整有效名称(全名=包名.类名)

  2. 这个类型直接父类的完整有效名(对于interface或是java.lang.object,都没有父类)

  3. 这个类型的修饰符(public,abstract,final的某个子集)

  4. 这个类型直接接口的一个有序列表

域(Field)信息

方法(Method)信息

JVM必须保存所有方法的以下信息,同域信息一样包括声明顺序:

每个异常处理的开始位置、结束位置、代码处理在程序计数器中的偏移地址、被捕获的异常类的常量池索引

non-final的类变量

/**
 * non-final的类变量
 *
 */
public class MethodAreaTest {
    public static void main(String[] args) {
        Order order = new Order();
        order.hello();
        System.out.println(order.count);
    }
}
class Order {
    public static int count = 1;
    public static final int number = 2;
    public static void hello() {
        System.out.println("hello!");
    }
}

如上代码所示,即使我们把order设置为null,也不会出现空指针异常

全局常量 同时使用 static final 进行修饰

运行时常量池 VS 常量池

java中的Person是什么

常量池

java中的Person是什么

为什么需要常量池?

一个java源文件中的类、接口,编译后产生一个字节码文件。而Java中的字节码需要数据支持,通常这种数据会很大以至于不能直接存到字节码里,换另一种方式,可以存到常量池,这个字节码包含了指向常量池的引用。在动态链接的时候会用到运行时常量池,之前有介绍。

比如:如下的代码:

public class SimpleClass {
    public void sayHello() {
        System.out.println("hello");
    }
}

虽然上述代码只有194字节,但是里面却使用了String、System、PrintStream及Object等结构。这里的代码量其实很少了,如果代码多的话,引用的结构将会更多,这里就需要用到常量池了。

常量池中有什么

例如下面这段代码

public class MethodAreaTest2 {
    public static void main(String args[]) {
        Object obj = new Object();
    }
}

将会被翻译成如下字节码

new #2  
dup
invokespecial
小结

运行时常量池

五 方法区使用举例

如下代码

public class MethodAreaDemo {
    public static void main(String args[]) {
        int x = 500;
        int y = 100;
        int a = x / y;
        int b = 50;
        System.out.println(a+b);
    }
}

字节码执行过程展示

java中的Person是什么

首先现将操作数500放入到操作数栈中

java中的Person是什么

然后存储到局部变量表中

java中的Person是什么

然后重复一次,把100放入局部变量表中,最后再将变量表中的500 和 100 取出,进行操作

java中的Person是什么

将500 和 100 进行一个除法运算,在把结果入栈

java中的Person是什么

在最后就是输出流,需要调用运行时常量池的常量

java中的Person是什么

最后调用invokevirtual(虚方法调用),然后返回

java中的Person是什么

返回时

java中的Person是什么

程序计数器始终计算的都是当前代码运行的位置,目的是为了方便记录 方法调用后能够正常返回,或者是进行了CPU切换后,也能回来到原来的代码进行执行。

六 方法区的演进细节

  1. 首先明确:只有Hotspot才有永久代。BEA JRockit、IBMJ9等来说,是不存在永久代的概念的。原则上如何实现方法区属于虚拟机实现细节,不受《Java虚拟机规范》管束,并不要求统一

  2. Hotspot中方法区的变化:

JDK1.6及以前有永久代,静态变量存储在永久代上
JDK1.7有永久代,但已经逐步 “去永久代”,字符串常量池,静态变量移除,保存在堆中
JDK1.8及之后无永久代,类型信息,字段,方法,常量保存在本地内存的元空间,但字符串常量池、静态变量仍然在堆中。

JDK6的时候

java中的Person是什么

JDK7的时候

java中的Person是什么

JDK8的时候,元空间大小只受物理内存影响

java中的Person是什么

为什么永久代要被元空间替代?

JRockit是和HotSpot融合后的结果,因为JRockit没有永久代,所以他们不需要配置永久代

1)为永久代设置空间大小是很难确定的。

在某些场景下,如果动态加载类过多,容易产生Perm区的oom。比如某个实际Web工 程中,因为功能点比较多,在运行过程中,要不断动态加载很多类,经常出现致命错误。

“Exception in thread‘dubbo client x.x connector'java.lang.OutOfMemoryError:PermGen space”

而元空间和永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。 因此,默认情况下,元空间的大小仅受本地内存限制。

2)对永久代进行调优是很困难的。

有些人认为方法区(如HotSpot虚拟机中的元空间或者永久代)是没有垃圾收集行为的,其实不然。《Java虚拟机规范》对方法区的约束是非常宽松的,提到过可以不要求虚拟机在方法区中实现垃圾收集。事实上也确实有未实现或未能完整实现方法区类型卸载的收集器存在(如JDK11时期的ZGC收集器就不支持类卸载)。 一般来说这个区域的回收效果比较难令人满意,尤其是类型的卸载,条件相当苛刻。但是这部分区域的回收有时又确实是必要的。以前sun公司的Bug列表中,曾出现过的若干个严重的Bug就是由于低版本的HotSpot虚拟机对此区域未完全回收而导致内存泄漏

方法区的垃圾收集主要回收两部分内容:常量池中废弃的常量和不在使用的类型

StringTable为什么要调整位置

静态变量存放在那里?

静态引用对应的对象实体始终都存在堆空间

可以使用 jhsdb.exe,需要在jdk9的时候才引入的

staticobj随着Test的类型信息存放在方法区,instanceobj随着Test的对象实例存放在Java堆,localobject则是存放在foo()方法栈帧的局部变量表中。

java中的Person是什么

测试发现:三个对象的数据在内存中的地址都落在Eden区范围内,所以结论:只要是对象实例必然会在Java堆中分配。

接着,找到了一个引用该staticobj对象的地方,是在一个java.lang.Class的实例里,并且给出了这个实例的地址,通过Inspector查看该对象实例,可以清楚看到这确实是一个java.lang.Class类型的对象实例,里面有一个名为staticobj的实例字段:

java中的Person是什么

从《Java虚拟机规范》所定义的概念模型来看,所有Class相关的信息都应该存放在方法区之中,但方法区该如何实现,《Java虚拟机规范》并未做出规定,这就成了一件允许不同虚拟机自己灵活把握的事情。JDK7及其以后版本的HotSpot虚拟机选择把静态变量与类型在Java语言一端的映射class对象存放在一起,存储于Java堆之中,从我们的实验中也明确验证了这一点

六 方法区的垃圾回收

有些人认为方法区(如Hotspot虚拟机中的元空间或者永久代)是没有垃圾收集行为的,其实不然。《Java虚拟机规范》对方法区的约束是非常宽松的,提到过可以不要求虚拟机在方法区中实现垃圾收集。事实上也确实有未实现或未能完整实现方法区类型卸载的收集器存在(如JDK11时期的zGC收集器就不支持类卸载)。

一般来说这个区域的回收效果比较难令人满意,尤其是类型的卸载,条件相当苛刻。但是这部分区域的回收有时又确实是必要的。以前sun公司的Bug列表中,曾出现过的若干个严重的Bug就是由于低版本的HotSpot虚拟机对此区域未完全回收而导致内存泄漏。

方法区的垃圾收集主要回收两部分内容:常量池中废弃的常量和不再使用的类型。

总结

java中的Person是什么

关于java中的Person是什么就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

推荐阅读:
  1. var p1 = new Person
  2. java中的类库是什么

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

java person

上一篇:如何设置一个DIV块固定在屏幕中央

下一篇:ajax网络请求封装的示例分析

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》