当前位置: 首页 > 编程日记 > 正文

JAVA 继承内存模型_Java内存模型

JVM的组成

类加载器(classloader)

执行引擎(execution engine)

运行时数据区域(runtime data area)

45158506213b61df310e8c7b8b0641c7.png

对于Java程序员来说,在虚拟机自动内存管理机制下,不再需要像C/C++程序开发程序员这样为内一个new 操作去写对应的delete/free操作,不容易出现内存泄漏和内存溢出问题。

正是因为Java程序员把内存控制权利交给Java虚拟机,一旦出现内存泄漏和溢出方面的问题,如果不了解虚拟机是怎样使用内存的,那么排查错误将会是一个非常艰巨的任务。

类加载器

顾名思义,类加载器用来加载Java类到Java虚拟机中, Java源文件(.java) 经过Java编译器编译之后就被转换成 字节码文件(.class) ,类加载器就负责读取Java字节代码,并转换成一个 类的实例(java.lang.Class) ,每个这样的实例用来表示一个Java类,这个类由它的类加载器和这个类本身一同确立在Java虚拟机中的唯一性,通过此实例的newInstance()方法就可以创建出该类的一个对象。

类加载器的结构

Java中的类加载器大致可以分为两类,一类是系统提供的,另外一类是由开发人员编写的

569ddaf397cc4421a430cb1ab26745e0.png

根类加载器:也叫引导类加载器、启动类加载器。负责将存放在 ++\lib++ 目录中的,或者被 ++-Xbootclasspath++ 参数所指定的路径中的,并且是虚拟机识别的类库加载到虚拟机内存中。

扩展类加载器:负责加载 ++\lib\ext++ 目录下的,或者被 ++java.ext.dirs++ 系统变量所指定的路径中的所有类库,开发者可以直接使用扩展类加载器。

应用类加载器:由于这个类加载器是ClassLoader中的getSystemClassLoader方法的返回值,所以也叫 ++系统类加载器++ 。它负责加载用户类路径上所指定的类库,开发者可以直接使用这个类加载器,如果应用程序中没有自定义过自己的类加载器。一般情况下这个就是程序中默认的类加载器。

这种类加载的层次关系,称为类加载器的双亲委派模型。

双亲委派模型

双亲委派模型是指当我们调用类加载器进行类加载时,该类加载器首先请求它的父类加载器进行加载,依次递归。

如果所有的父类加载器都加载失败,则当前类加载器自己进行加载操作。

以下用ClassLoader类的源码进行逻辑分析:

protected Class> loadClass(String name, boolean resolve)

throws ClassNotFoundException

{

//进行类加载操作时首先要加锁,避免并发加载

synchronized (getClassLoadingLock(name)) {

//首先判断指定类是否已经被加载过

Class> c = findLoadedClass(name);

if (c == null) {

long t0 = System.nanoTime();

try {

if (parent != null) {

//如果当前类没有被加载且父类加载器不为null,则请求父类加载器进行加载操作

c = parent.loadClass(name, false);

} else {

//如果当前类没有被加载且父类加载器为null,则请求根类加载器进行加载操作

c = findBootstrapClassOrNull(name);

}

} catch (ClassNotFoundException e) {

}

if (c == null) {

long t1 = System.nanoTime();

//如果父类加载器加载失败,则由当前类加载器进行加载,

c = findClass(name);

//进行一些统计操作

sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);

sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);

sun.misc.PerfCounter.getFindClasses().increment();

}

}

//初始化该类

if (resolve) {

resolveClass(c);

}

return c;

}

}

这里有几个细节需要说明

ClassLoader类是一个抽象类,但却没有包含任何抽象方法;

如果要实现自己的类加载器且不破坏双亲委派模型,只需要继承ClassLoader类并重写findClass方法;

如果要实现自己的类加载器且破坏双亲委派模型,则需要继承ClassLoader并重写findClass和loadClass方法;

为什么使用双亲委派模型

确保无论使用哪个类加载器加载,最终都会委派给最顶端的启动类加载器加载,从而使得不同加载器加载的类都是同一个类,保障了Java核心类库的安全问题。

相反,如果没有双亲委派模型,由各个类加载器自己加载的话,如果开发者自己写了一个称为java.lang.Object的类并放在classpath下那么系统将会出现很多个不同的Object类,Java类型体系中最基础的行为也就无法保证。

执行引擎

类加载器负责装载编译后的字节码,并加载到运行时数据区,执行引擎则会执行这些字节码。

执行引擎以指令为单位读取Java字节码,它像一个CPU一样,一条一条地执行机器指令,每个字节码指令都由1字节的操作码和附加的操作数来执行任务,完成后就继续执行下一条操作码。

虚拟机实现中,可能会有两种的执行方式:

解释执行(通过解释器执行)

编译执行(通过即时编译器产生本地代码)

有些虚拟机值采用一种执行方式,但是有点采用了两种,甚至有可能包含几个不同级别的编译器执行引擎。

所有的Java虚拟机的执行引擎都是一致的:输入的是字节码文件、处理过程是等效字节码解析过程,输出的是执行结果。

这里的坑太深,建议 ->详情请看这里

运行时数据区

Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域

这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则是依赖用户线程的启动和结束而建立和销毁。

8ec825e71ce6084624259225eca87282.png

线程共享的: 堆、方法区

线程私有的: (虚拟机)栈、本地方法栈、程序计数器

堆可以被多个线程共享;

堆用来存放对象和数组(特殊的对象),几乎所有的对象实例都在这里分配,可以说堆只存放对象;

堆随着虚拟机启动而创建;

堆是垃圾回收机制管理的主要区域,也称GC堆;

堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可

堆可以是可动态扩展内存的,如果堆内存剩余的内存不足以满足对象的创建,也不能扩展时,就会抛出OOM错误

方法区

方法区可以被多个线程共享;

方法区用来存放

每个类的信息(包括类名、方法信息、字段信息);

静态变量;

常量;

编译器编译后的代码;

可以选择不实现垃圾收集;

方法区还包含常量池,用来存储编译期间生成的字面量和符号引用;

方法区中还有一个重要的部分是运行时常量池,它是每一个类或接口的常量池的运行时表示形式,在类和接口被加载进JVM后,对应的运行时常量池就被创建出来;

属于线程私有,生命周期与线程相同;

每个方法执行的同时都会创建一个栈帧,里面包含:

局部变量表

操作数栈

动态链接

方法出口

等等

方法执行时入栈,执行完出栈,先进后出;

在栈中可能出现两种错误:

StackOverflowError:出现在内存设置为固定值的时候,需要的内存超过设定的固定值时;

OutOfMemoryError:出现在内存设置为动态增长的时候,申请内存大小超过可用内存时;

在方法中定义的基本类型变量和对象引用变量都会在栈内存中分配,当该变量退出其作用域后,Java会自动释放所占用的内存

本地方法栈

每个线程独有的;

与虚拟机栈类似,但是虚拟机栈服务的是Java方法,本地方法栈是为JVM所调用到的Native方法服务;

并不是由Java语言实现的栈;

程序计数器

用来记录当前线程正在执行的指令,线程私有的;

字节码解释器就是通过改变这个计数器的值来选取下一条需要执行的字节码指令

如果当前正在执行的方法时本地方法,那么计数器的值为undefined;

这个区域是唯一一个不会抛出OOM错误的数据区

相关文章:

Error: The INF file contains Unicode characters that could not be converted correctly

昨天第一次为自己的windows mobile程序制作CAB安装包,但是在生成过程中,却出现了这样一个问题:编译完成 -- 0 个错误,0 个警告time -> G:\WindowsMobile\time\time\bin\Debug\time.exe------ 正在启动项目“SmartDeviceCab1”的…

嵌入式开发板设置无密码登录

本次配置需要修改的ssh登录的配置文件 vi /etc/ssh/sshd_config允许root用户远程登录 设置PermitRootLogin参数值为yes #LoginGraceTime 2m PermitRootLogin yes #StrictModes yes #MaxAuthTries 6 #MaxSessions 10允许无密码登录 设置PermitEmptyPasswords 参数值修改为ye…

2012/08/27 夜

杂记于2012/08/27 唉,,最近公司在搬家,一直没有时间来看技术方面的资料,丫的上个星期天还接到第二天凌晨3点钟呢。。。唉。。有点受不了啊。。这苦逼的运维工作,,,呵,来说说这其中让…

存储过程和函数 PROCEDURE FUNCTION

SQL语句执行的时候,要首先编译,然后在被执行。在大型数据库系统中,为了提高效率,将为了完成特定功能的SQL语句集进行编译优化后,存储在数据库服务器中,用户通过指定存储过程的名字来调用执行。 具体而言&am…

Android——学习:线性布局权重分配

LinearLayout在Android中被广泛使用,LinearLayout有一个比较重要的属性——android:layout_weight。按照字面理解就是该控件的权重,这个值默认是 零(0)。 举个例子: 在下图中,整个界面是一个Linearlayout&a…

java bean配置文件_Spring中多配置文件及引用其他bean的方式

Spring多配置文件有什么好处?按照目的、功能去拆分配置文件,可以提高配置文件的可读性与维护性,如将配置事务管理、数据源等少改动的配置与配置bean单独分开。Spring读取配置文件的几种方式:1、使用Spring自身提供的ApplicationCo…

putty 串口登录开发板

安装putty 多个平台均可以安装putty pc端配置 使用串口线连接开发板 ls /dev 查看是否出现类似于ttyUSBx的文件 sudo putty 弹出页面,选择Serial Serial line填写/dev/ttyUSBx Speed填写115200(根据不同开发板,选择不同参数) 依次点击Load&#xff0…

win7下解决Android SDK Manger慢

2019独角兽企业重金招聘Python工程师标准>>> 今天准备做个Android小程序,以前配置的环境太久了,于是想配最新,但是花了大半天的时间遇到各种问题,最终还是配置好了。 1、首先修改C:\Windows\System32\drivers\etc\host…

Linux 工具进阶

参考网址 https://linuxtools-rst.readthedocs.io/zh_CN/latest/advance/index.html 转载于:https://www.cnblogs.com/artesian0526/p/9712258.html

ASP.NET MVC:利用ASP.NET MVC4的IBundleTransform集成LESS

背景 LESS确实不错,只是每次写完LESS都要手工编译一下有点麻烦(VS插件一直没有安装好),昨天在官方看到了如何用IBundleTransform集成LESS,今天就记录一下。 参考资料:http://www.asp.net/mvc/tutorials/mvc…

java锁屏_JAVA设置桌面不锁屏设置

//下面是编译命令// javac -encoding utf-8 Main.javaimport javax.swing.*;import java.awt.*;import java.awt.event.*;public class Main extends WindowAdapter {JLabel label null;public Main() {JFrame jFrame new JFrame("保持打开就不会锁屏");Container …

网线直连开发板

pc 端配置 点击pc端无线链接图标编辑链接以太网编辑IPv4设置方法:与其他计算机共享根据putty获取的动态ip使用ssh登录 解决 ip 无法登录问题 设置 pc 端 ip 和开发板 ip 在同一个网段 比如开发板 ip 是 10.42.0.123 可以设置自己机器的 ip 为 10.42.0.11 sudo i…

linux系统中指定端口连接数限制

限制22端口只能有两个连接 [code] iptables -P INPUT DROP iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A INPUT -p tcp --dport 22 -m connlimit --connlimit-above 2 -j REJECT iptables -A INPUT -p tcp --dport 22 -j ACCEPT [/code] 在此…

PHP-错误处理

错误处理 一、错误的分类 1、语法错误: 程序没法运行,直接提示语法错误。 2、运行时错误: 只有程序运行到某行,或在某些特定的情形下运行才会发生的错误。 3、逻辑错误: 程序从头到尾运行都没有发生(并提示…

C语言的变量的内存分配

今晚看了人家写的一个关于C语言内存分配的帖子&#xff0c;发现真是自己想找的&#xff0c;于是乎就收藏了。。。 先看一下两段代码&#xff1a; char* toStr() {char *s "abcdefghijkl";return s; } int main() {cout << toStr() << endl;return 0; }…

java打包_java工程打包(方式一)

1、新建工程myprojectpackage cn.zj;public class TestMain {public static void main(String[] args) {System.out.println("Hello World!");}}2、右击Java工程选择Export—>选择JAR file—>Next3、选择要打包的文件&#xff0c;不需要的文件不必打包&#xf…

s32v 开发板安装 apex 驱动

安装驱动 首先要获取到 apex.ko 文件&#xff0c;这个应该是硬件厂商提供&#xff0c;执行下面命令安装 首先需要给 apex.so 文件加上可执行权限 insmod apex.ko查看是否安装成功 执行下面命令&#xff0c;查看是否安装成功&#xff0c;如果安装成功&#xff0c;执行的结果中…

android常见错误与问题

1. Unable to start activity ComponentInfo 原因有很多种&#xff0c;我碰到一种&#xff1a; 可能是当前Activity里引用的View&#xff0c;并不存在于绑定的Layout里&#xff0c;而是在其他的Layout里&#xff0c;在Copy代码的时候&#xff0c;常会发生这种问题。

链式前向星(模板)

一种非常厉害的存图的数据结构&#xff01; 本质&#xff1a;模拟链表的操作&#xff0c;链式存储图。&#xff08;2&#xff0c;3都可以模拟链表的操作&#xff0c;替代链表&#xff09; &#xff08;1&#xff09;二维数组存图&#xff1a;Map[x][y]&#xff0c;一维代表出发…

tar 打包问题

项目中使用到 tar 文件&#xff0c;同一个 tar 文件解压之后在压缩&#xff0c;在程序执行的时候不能使用了 原因是 tar 对文件名长度有限制&#xff0c;当文件名过程的时候&#xff0c;使用 --formatustar 进行压缩

QT webkit学习笔记(2)

五、QWebDataBase Class介绍 QWebDataBase提供了对基于JavaScript创建的HTML 5数据库。新一代的HTML 5标准也提供对基于javaScript SQL数据库访问的支持。QWebDataBase就是这些数据库的C接口。关于HTML 5的详情&#xff0c;可以参见HTML 5 Draft Standard. 六、QWebHistory Cla…

java 数组越界异常_数组越界异常 求解决!!!

源自&#xff1a;4-3 滚动状态判断与处理数组越界异常 求解决&#xff01;&#xff01;&#xff01;package com.example.imooc;import java.io.BufferedInputStream;import java.io.IOException;import java.io.InputStream;import java.net.HttpURLConnection;import java.ne…

WPF外包公司—北京动点软件WPF最新的电子书整理打包下载

最近看到很多朋友寻找以前的WPF电子书&#xff0c;其实这些书在书店目前是很难买到了&#xff0c;不过还是很经典的&#xff0c;希望大家收藏~ WPF揭秘 http://download.csdn.net/detail/ping_vip/3935100 WPF经典教程 http://kiccp.sinaapp.com/store/info/83 WPF程序设计指南…

java后端判断用户是否关注公众号

/*** 判断用户是否关注了公众号* param openid* return*/ public static boolean judgeIsFollow(String openid){int subscribe 0; // String url "https://api.weixin.qq.com/cgi-bin/user/info?access_token"token"&openid"openid"&a…

QtCreator动态编译jsoncpp完美支持x86和arm平台

如果是做嵌入式开发。 在Qt下支持JSon最好的办法&#xff0c;可能不是采用qjson这个库。QJson这个库的实例只提供了x86环境下的编译方法。 Installing QJson-------------- QJson requires:- Qt 4.0 or greater- cmake 2.6 or greater For Unix/Linux/Mac: mkdir build cd b…

RADStudio连接MySQL_使用FireDac(Delphi)在Firebird中创建数据库

我最近从AnyDac改为FireDac(8.0.5.3365).我们正在运行Delphi 2006.当我使用此组件的AnyDac版本时,我可以通过执行以下操作来创建新数据库.设置我的连接fConnection.LoginPrompt : false;fConnection.ResourceOptions.SilentMode : true;fConnection.Params.Clear;fConnection.P…

valgrind 使用 kcachegrind 查看函数运行时间

安装 首先安装运行分析函数时间的工具 kcachegrind 下载安装包 http://kcachegrind.sourceforge.net/&#xff0c;下载最新的 tar.gz 文件 解压文件&#xff0c;进入解压之后的目录&#xff0c;从 README 中可以找到安装方式&#xff0c;这里记录一下 cmake . make -j8 sudo …

Red Hat Enteripse Linux5下配置yum源的方法

1。确保RHEL5中已经安装了yum。2。修改源配置文件 &#xff03;gedit /etc/yum.repos.d/CentOS-Base.repo在其中加入以下内容[base]nameCentOS-5-Base#mirrorlisthttp://mirrorlist.centos.org/?release$releasever5&arch$basearch&repoos#baseurlhttp://mirror.cento…

echarts如何修改散点大小

由于工作需要 懵懵懂懂接触到了echarts 很牛逼 遇到的问题是如何修改散点图中点点的大小&#xff0c;其他的图我没有涉及哦~ demo地址 http://www.echartsjs.com/examples/editor.html?cscatter-single-axis 找到左侧代码 1 symbolSize: function (dataItem) { 2 3 return da…

字节跳动java笔试题目_牛客网--字节跳动面试题--特征提取

牛客网--字节跳动面试题--特征提取博客说明文章所涉及的资料来自互联网整理和个人总结&#xff0c;意在于个人学习和经验汇总&#xff0c;如有什么地方侵权&#xff0c;请联系本人删除&#xff0c;谢谢&#xff01;来源链接&#xff1a;特征提取 来源&#xff1a;牛客网题目小明…