-
论文研究-基于轮廓的图像区域划分方法的研究 .pdf
2019-08-27 02:19:03基于轮廓的图像区域划分方法的研究,覃征,陈旸,本文针对图像融合问题,提出了基于轮廓的联合区域划分的方法。对于像素级融合来说,区域划分的结果将作为图像融合的基本单元,因 -
突出煤层突出危险区域划分的新方法
2020-02-08 00:32:03突出煤层突出危险区域划分的新方法,翟果红,蒋承林,介绍了一种新的突出煤层危险区域划分方法,分析了利用初始释放瓦斯膨胀能指标划分突出危险区域的理论、划分步骤和优点;并利用该 -
研究论文-移动视频监控的预警区域划分方法.pdf
2019-08-07 15:25:54通过对现有的视频监控系统中预警区域划分方法的分析,结合移动视频监控系统的特点,提出 2 种适用于移动视频监控的预警区域划分方法。 九宫格预警区域划分方法,利用布局文件实现,用 M 行 N 列的单元格填充整个... -
企业网络安全区域划分的原则和方法
2019-01-22 22:14:00企业网络安全区域划分的原则和方法 点击蓝字关注企业网络安全区域划分的原则和方法
点击蓝字关注? talkwithtrend 今天网络逐渐成为企业运营不可或缺的一部分,基于互联网的应用、远程培训、在线订购以及财务交易等,极大地提高企业的生产力和盈利能力,带来很多的便利。
但在享受便利的同时,网络系统同样也成为安全威胁的首要目标,网络安全面临着前所未有的威胁。威胁不仅来自人为的破坏,也来自自然环境。各种人员、机构出于各种目的攻击行为,系统自身的安全缺陷(脆弱性),以及自然灾难,都可能构成对企业网络系统的威胁。
威胁的发起因素是威胁的主体, 按威胁主体的性质分类, 安全威胁可以分为人为的安全威胁和非人为的安全威胁。按人为攻击的方式分类,可以分为被动攻击、主动攻击、邻近攻击和分发攻击等。
1、安全威胁
非人为的安全威胁
非人为的安全威胁主要分为两类,一类是自然灾难,另一类是技术局限性。信息系统都是在一定的物理环境下运行, 自然灾难对信息系统的威胁是非常严重的。 典型的自然灾难包括:地震、水灾、火灾、风灾等。自然灾难可能会对信息系统造成毁灭性的破坏。
同所有技术一样,信息技术本身也存在局限性,有很多缺陷和漏洞。典型的缺陷包括:系统、硬件、软件的设计缺陷、实现缺陷和配置缺陷。信息系统的高度复杂性以及信息技术的高速发展和变化,使得信息系统的技术局限性成为严重威胁信息系统安全的重大隐患。
人为安全威胁
网络系统面临的人为安全威胁可分为外部威胁和内部威胁,人为安全威胁主要是人为攻击,主要分为以下几类:被动攻击、主动攻击、邻近攻击、分发攻击。
被动攻击
这类攻击主要包括被动监视通信信道上的信息传送。被动攻击主要是了解所传送的信息,一般不易被发现。典型攻击行为有:
a) 监听通信数据;
b) 解密加密不善的通信数据;
c) 口令截获;
d) 通信流量分析。
主动攻击
主动攻击为攻击者主动对信息系统实施攻击,包括企图避开安全保护,引入恶意代码,以及破坏数据和系统的完整性。
a) 修改数据;
b) 重放所截获的数据;
c) 插入数据;
d) 盗取合法建立的会话;
e) 伪装;
f) 越权访问;
g) 利用缓冲区溢出(BOF)漏洞执行代码;
h) 插入和利用恶意代码(如:特洛依木马、后门、病毒等);
i) 利用协议、软件、系统故障和后门;
j) 拒绝服务攻击。
邻近攻击
此类攻击的攻击者试图在地理上尽可能接近被攻击的网络、系统和设备,目的是修改、收集信息,或者破坏系统。这种接近可以是公开的或秘密的,也可能是两种都有,邻近攻击最容易发生在没有良好保安措施的地方。典型的邻近攻击有:
a) 偷取磁盘后又还回;
b) 偷窥屏幕信息;
c) 收集作废的打印纸;
d) 物理毁坏通信线路。
分发攻击
分发攻击是指在系统硬件和软件的开发、生产、运输、安装和维护阶段,攻击者恶意修改设计、配置等行为。典型的分发攻击方式有:
a) 利用制造商在设备上设置隐藏的攻击途径;
b) 在产品分发、安装时修改软硬件配置,设置隐藏的攻击途径;
c) 在设备和系统维护升级过程中修改软硬件配置,设置隐藏的攻击途径。直接通过因特网进行远程升级维护具有较大的安全风险。
内部威胁
内部威胁是由于内部管理不善, 由内部合法人员造成, 他们具有对系统的合法访问权限。内部合法人员对系统的威胁, 除了具有上述人为安全威胁的攻击方式, 还具有其特有的攻击手段。内部威胁分为恶意和非恶意两种,即恶意攻击和非恶意威胁。恶意攻击是指出于各种目的而对所使用的信息系统实施的攻击。 非恶意威胁则是由于合法用户的无意行为造成了对政务信息系统的攻击,他们并非故意要破坏信息和系统,但由于误操作、经验不足、培训不足而导致一些特殊的行为,对系统造成了破坏。
典型的内部威胁有:
a) 恶意修改数据和安全机制配置参数;
b) 恶意建立未授权的网络连接,如:拨号连接;
c) 恶意的物理损坏和破坏;
d) 无意的数据损坏和破坏,如:误删除。
2、传统安全防范技术
面对如此众多的威胁威胁, 传统安全防范技术强调单个安全产品的重要性, 如防火墙的性能和功能,IDS 入侵检测系统的高效性等,而对全网的安全威胁没有一个仔细的研究,对网络安全的设计没有明确的层次和区域,如下图所示:
网络中部署了相关的安全产品,防火墙,VPN,IDS,安全管理等,但由于组网方式很随意,没有统一规划,不清楚网络的威胁,层次,区域策略,安全防护手段部署原则不明确,当网络某一局部出现安全隐患被侵入后,由于网络之间边界不清楚,无清楚的边界控制,攻击很容易扩散,从而局部侵入马上成为全网侵入,造成对全网的威胁。当局部的蠕虫泛滥,造成全网的快速泛滥,企业用户缺乏足够的缓冲处理时间,可能很快造成全网瘫痪,而部署的安全设备也不能充分的发挥作用,成为资源的浪费。3、纵深防御和安全区域划分
因此,在多种多样的安全威胁前,企业需要建立纵深防御体系,防止因某个部分的侵入而导致整个系统的崩溃;基于网络系统之间逻辑关联性和物理位置,功能特性,划分清楚的安全层次和安全区域,在部署安全产品和策略时,才可以定义清楚地安全策略和部署模式。
特别是对复杂的大系统,安全保障包括网络基础设施、业务网,办公网,本地交换网,电子商务网,信息安全基础设施等多个保护区域。这些区域是一个紧密联系的整体,相互间既有纵向的纵深关系,又有横向的协作关系,每个范围都有各自的安全目标和安全保障职责。积极防御、综合防范的方针为各个保护范围提供安全保障,有效地协调纵向和横向的关系,提高网络整体防御能力。
安全区域划分对企业网络的建设有着以下重要意义:
纵深防御依赖于安全区域的清除定义 安全区域间边界清晰,明确边界安全策略 加强安全区域策略控制力,控制攻击扩散,增加应对安全突发事件的缓冲处理时间 依据按全策略,可以明确需要部署的安全设备 使相应的安全设备充分运用,发挥应有的作用
安全域隔离技术
安全域隔离技术主要分为物理隔离技术和逻辑隔离技术两类
物理隔离 • 物理级(电磁辐射)-- 屏蔽、干扰 • 终端级(双网机)-- 双盘型、双区型 • 传输信道级 -- 非加密信道、加密信道 • 网络级(网闸) --信息交换型 --信息共享型 --系统互操作型 逻辑隔离 • 防火墙控制 • VLAN虚拟网技术 • FR, ATM技术 • L2TP V3,ATOM • IPsec VPN, MPLS VPN, SSL VPN, GRE技术 • 病毒网关过滤技术 • 应用层安全控制技术
4、一般企业网络安全区域设计模型
企业网络情况和业务系统千差万别, 所以不同企业对安全区域的划分, 可以有完全不同的表述方法和模式。但一般而言,大多数企业均有相同的网络部分和安全分区。
安全区域相关定义
在划分安全区域时,需要明确几个安全区域相关的定义,以免模糊他们之间的概念,造成区域划分完之后, 依然逻辑不清晰, 安全策略无法明确, 立体的纵深防御体系也无法建立。一般在安全区域划分时,需要明确如下常用的定义:
• 物理网络区域
物理网络区域是指数据网中,依照在相同的物理位置定义的网络区域,通常如办公区域,远程办公室区域,楼层交换区域等
• 网络功能区域
功能区域是指以功能为标准,划分的逻辑网络功能区域,如互联网区域,生产网区域,办公网区域等
• 网络安全区域
网络安全区域是指网络系统内具有相同安全要求、达到相同安全防护等级的区域。同一安全区域一般要求有统一的安全管理组织和安全防护体系及策略,不同的安全区域的互访需要有相应得边界安全策略
• 网络安全层次
根据层次分析方法,将网络安全区域划分成几个不同安全等级的层次,同一层次包含若干个安全等级相同的区域,同层安全区域之间相互逻辑或物理隔离。
• 物理网络区域和安全区域的关系
一个物理网络区域可以对应多个安全区域,一个安全区域只能对应一个物理网络区域
• 网络功能区域和物理网络区域的关系
一个网络功能区域可以对应多个物理网络区域,一个物理网络区域只能对应一个网络功能区域,如办公网功能区域,可以包含总部办公网物理区域,远程办公室办公网物理区域,移动办公物理区域等。
• 网络功能区域和安全区域的关系
一个网络功能区域可以对应多个网络安全区域,一个网络安全区域只能对应一个网络功能区域。
安全区域设计一般原则
尽管不同企业对安全区域的设计可能理解不尽相同, 但还是有一般的安全区域设计原则可供参考如下:
• 一 体化设计原则
综合考虑整体网络系统的需求,一个整体的网络安全区域设计规范以规范我
• 多重保护原则
不能把整个系统的安全寄托在单一的安全措施或安全产品上,要建立一套多重保护系统,各重保护相互补充,当一层保护被攻破时,其它层的保护仍可确保信息系统的安全
• 定义清楚的安全区域边界
设定 清楚地安全区域边界,可以明确安全区域策略,从而确定需要部署何种安全技术和设备
• 在安全域之间执行完整的策略
在安全域之间执行完整的安全策略,帮助建立完整的纵深防御体系,方便安全技术实施部署
• 通常安全域越多越好
• 较多的安全区域划分可以提供更精确的访问控制策略,提高网络的可控性
• 太多地安全区域,会增加管理复杂性
• 需要在较多的安全区域划分和管理的复杂性之间做出平衡选择
• 风险、代价平衡分析的原则
通过分析网络系统面临的各种安全问题挑战, 确保实施网络系统安全策略的成本与被保护资源的价值相匹配;确保安全防护的效果与网络系统的高效、健壮相匹配。
• 适应性、灵活性原则
在进行网络安全区域设计时,不能只强调安全方面的要求,要避免对网络、应用系统的发展造成太多的阻碍;另外,在网络安全区域模型保持相对稳定的前提下,要求整体安全区域架构可以根据实际安全需求变化进行微调,使具体网络安全部署的策略易于修改,随时做出调整。
网络安全区域划分方法
传统的划分方法
传统安全区域划分方法基本是以安全功能区域和物理区域相结合,做出安全区域的划分。 在一般规模较小的企业网络环境中,这种方式简明, 方便,逻辑清楚, 便于实施。但在先对比较复杂的企业网络系统中, 应用系统相对复杂, 传统方式主要考虑不同应用系统之间安全防护等级的不同, 较少考虑同一应用系统对外提供服务时内部不同层次之间存在的安全等级差异,一般而言,存在以下4个方面缺点:
• 在应用系统较为复杂的网络系统中,不同应用系统的用户层、表示层功能相互整合,各应用系统不同层次间的联系日趋复杂,从而很难设定明确的界限对应用系统进行归类,造成安全区域边界模糊。 • 设置在安全区域边界的防火墙实施的安全策略级别不清, 存在着应用划分层次(用户、表示、应用、数据) 4 层功能两两之间各种级差的访问控制策略,防火墙安全等级定位不清,不利于安全管理和维护。 • 所有区域定义的安全级别过于复杂,多达 10+级安全等级,等级高低没有严格的划分标准,造成实施边界防护时难以进行对应操作。 • 逻辑网络安全区域和物理网络区域的概念不清,相互混用,无法明确指出两者之间的相互关系。 改进的安全区域划分方法- 层次型安全区域划分方法
借鉴 B/S 结构应用系统对外提供服务的层次关系,采用层次分析的方法,将数据网络划分成核心数据层、应用表述层、网络控制层、用户接入层 4 个不同的安全等级,从核心数据层到用户接入层安全等级递减。不同安全层次等级之间由于存在较大安全级差,需要通过防火墙实施物理隔离和高级别防护;同一安全等级层次内的资源,根据对企业的重要性不同,以及面临的外来攻击威胁、内在运维风险不同, 进一步划分成多个安全区域, 每个区域之间利用防火墙、 IOS ACL、VLAN 实施逻辑、物理的隔离,形成一个垂直分层,水平分区的网络安全区域模型。
(本文来源网络,作者佚名)
-
CFI中基于动态区域划分的非平稳杂波抑制方法
2020-10-16 16:13:52在超声彩色血流成像(Color Flow Imaging,简称CFI)系统中,为抑制杂波信号对血流速度估计的影响,提出了一种基于动态区域划分的非平稳杂波抑制方法。该方法首先根据回波信号的能量特性提出动态区域划分法,将回波信号... -
古山矿采空区危险区域划分方法比较
2020-04-26 11:31:19为解决古山三井综放工作面采空区自燃防治及危险区域划分的难题,并探究采用温升率划分自燃危险区域的可靠性和确定合理指标值,通过采用现场气体和温度监测与理论分析相结合的方法,研究综放工作面采空区氧气浓度和温度... -
基于区域划分自适应粒子群优化的超短基线定位算法
2021-01-12 22:36:37该算法将声速作为未知量,利用冗余的定位信息构建定位模型,针对标准粒子群算法收敛速度慢及容易早熟的问题,采用区域划分的方法动态调整粒子的惯性权重和学习因子,达到寻优能力与收敛速度的平衡,并引入自适应变异操作... -
论文研究-LION:基于位置信息与兴趣偏好的P2P网络区域划分方法 .pdf
2019-08-20 09:09:27LION:基于位置信息与兴趣偏好的P2P网络区域划分方法,董丽华,卢美莲,P2P技术的广泛应用使得构建一个合理的P2P覆盖网拓扑结构显得至关重要。针对结构化P2P覆盖网存在不支持语义查询及物理网络与逻辑网络 -
小白都能看懂的java虚拟机内存区域划分
2019-11-26 17:21:273.方法区 对象组成 4.本地方法栈 5.堆 GC GC案例 一、虚拟机 同样的java代码在不同平台生成的机器码肯定是不一样的,因为不同的操作系统底层的硬件指令集是不同的。 同一个java代码在windows上生成...目录
一、虚拟机
同样的java代码在不同平台生成的机器码肯定是不一样的,因为不同的操作系统底层的硬件指令集是不同的。
同一个java代码在windows上生成的机器码可能是0101.......,在linux上生成的可能是1100......,那么这是怎么实现的呢?
不知道同学们还记不记得,在下载jdk的时候,我们在oracle官网,基于不同的操作系统或者位数版本要下载不同的jdk版本,也就是说针对不同的操作系统,jdk虚拟机有不同的实现。
那么虚拟机又是什么东西呢,如图是从软件层面屏蔽不同操作系统在底层硬件与指令上的区别,也就是跨平台的由来。
说到这里同学们可能还是有点不太明白,说的还是太宏观了,那我们来了解下java虚拟机的组成。
二、虚拟机组成
1.栈
我们先讲一下其中的一块内存区域栈,大家都知道栈是存储局部变量的,也是线程独有的区域,也就是每一个线程都会有自己独立的栈区域。
public class Math { public static int initData = 666; public static User user = new User(); public int compute() { int a = 1; int b = 2; int c = (a+b) * 10; return c; } public static void main(String[] args) { Math math = new Math(); math.compute(); System.out.println("test"); } }
说起栈大家都不会陌生,数据结构中就有学,这里线程栈中存储数据的部分使用的就是栈,先进后出。
大家都知道每个方法都有自己的局部变量,比如上图中main方法中的math,compute方法中的a b c,那么java虚拟机为了区分不同方法中局部变量作用域范围的内存区域,每个方法在运行的时候都会分配一块独立的栈帧内存区域,我们试着按上图中的程序来简单画一下代码执行的内存活动。
执行main方法中的第一行代码是,栈中会分配main()方法的栈帧,并存储math局部变量,,接着执行compute()方法,那么栈又会分配compute()的栈帧区域。
这里的栈存储数据的方式和数据结构中学习的栈是一样的,先进后出。当compute()方法执行完之后,就会出栈被释放,也就符合先进后出的特点,后调用的方法先出栈。
栈帧
那么栈帧内部其实不只是存放局部变量的,它还有一些别的东西,主要由四个部分组成。
那么要讲这个就会涉及到更底层的原理--字节码。我们先看下我们上面代码的字节码文件。
看着就是一个16字节的文件,看着像乱码,其实每个都是有对应的含义的,oracle官方是有专门的jvm字节码指令手册来查询每组指令对应的含义的。那我们研究的,当然不是这个。
jdk有自带一个javap的命令,可以将上述class文件生成一种更可读的字节码文件。
我们使用javap -c命令将class文件反编译并输出到TXT文件中。
Compiled from "Math.java" public class com.example.demo.test1.Math { public static int initData; public static com.example.demo.bean.User user; public com.example.demo.test1.Math(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return public int compute(); Code: 0: iconst_1 1: istore_1 2: iconst_2 3: istore_2 4: iload_1 5: iload_2 6: iadd 7: bipush 10 9: imul 10: istore_3 11: iload_3 12: ireturn public static void main(java.lang.String[]); Code: 0: new #2 // class com/example/demo/test1/Math 3: dup 4: invokespecial #3 // Method "<init>":()V 7: astore_1 8: aload_1 9: invokevirtual #4 // Method compute:()I 12: pop 13: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream; 16: ldc #6 // String test 18: invokevirtual #7 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 21: return static {}; Code: 0: sipush 666 3: putstatic #8 // Field initData:I 6: new #9 // class com/example/demo/bean/User 9: dup 10: invokespecial #10 // Method com/example/demo/bean/User."<init>":()V 13: putstatic #11 // Field user:Lcom/example/demo/bean/User; 16: return }
此时的jvm指令码就清晰很多了,大体结构是可以看懂的,类、静态变量、构造方法、compute()方法、main()方法。
其中方法中的指令还是有点懵,我们举compute()方法来看一下:
Code: 0: iconst_1 1: istore_1 2: iconst_2 3: istore_2 4: iload_1 5: iload_2 6: iadd 7: bipush 10 9: imul 10: istore_3 11: iload_3 12: ireturn
这几行代码就是对应的我们代码中compute()方法中的四行代码。大家都知道越底层的代码,代码实现的行数越多,因为他会包含一些java代码在运行时底层隐藏的一些细节原理。
那么一样的,这个jvm指令官方也是有手册可以查阅的,网上也有很多翻译版本,大家如果想了解可自行百度。
这里我只讲解本博文设计代码中的部分指令含义:
0. 将int类型常量1压入操作数栈
0: iconst_1
这一步很简单,就是将1压入操作数栈
1. 将int类型值存入局部变量1
1: istore_1
局部变量1,在我们代码中也就是第一个局部变量a,先给a在局部变量表中分配内存,然后将int类型的值,也就是目前唯一的一个1存入局部变量a
2. 将int类型常量2压入操作数栈
2: iconst_2
3. 将int类型值存入局部变量2
3: istore_2
这两行代码就和前两行类似了。
4. 从局部变量1中装载int类型值
4: iload_1
5. 从局部变量2中装载int类型值
5: iload_2
这两个代码是将局部变量1和2,也就是a和b的值装载到操作数栈中
6. 执行int类型的加法
6: iadd
iadd指令一执行,会将操作数栈中的1和2依次从栈底弹出并相加,然后把运算结果3在压入操作数栈底。
7. 将一个8位带符号整数压入栈
7: bipush 10
这个指令就是将10压入栈
8. 执行int类型的乘法
9: imul
这里就类似上面的加法了,将3和10弹出栈,把结果30压入栈
9. 将将int类型值存入局部变量3
10: istore_3
这里大家就不陌生了吧,和第二步第三步是一样的,将30存入局部变量3,也就是c
10. 从局部变量3中装载int类型值
11: iload_3
这个前面也说了
11. 返回int类型值
12: ireturn
这个就不用多说了,就是将操作数栈中的30返回
到这里就把我们compute()方法讲解完了,讲完有没有对局部变量表和操作数栈的理解有所加深呢?说白了赋值号=后面的就是操作数,在这些操作数进行赋值,运算的时候需要内存存放,那就是存放在操作数栈中,作为临时存放操作数的一小块内存区域。
接下来我们再说说方法出口。
方法出口说白了不就是方法执行完了之后要出到哪里,那么我们知道上面compute()方法执行完之后应该回到main()方法第三行那么当main()方法调用compute()的时候,compute()栈帧中的方法出口就存储了当前要回到的位置,那么当compute()方法执行完之后,会根据方法出口中存储的相关信息回到main()方法的相应位置。
那么main()方同样有自己的栈帧,在这里有些不同的地方我们讲一下。
我们上面已经知道局部变量会存放在栈帧中的局部变量表中,那么main()方法中的math会存入其中,但是这里的math是一个对象,我们知道new出来的对象是存放在堆中的
那么这个math变量和堆中的对象有什么联系呢?是同一个概念么?
当然不是的,局部变量表中的math存储的是堆中那个math对象在堆中的内存地址
2.程序计数器
程序计数器也是线程私有的区域,每个线程都会分配程序计数器的内存,是用来存放当前线程正在运行或者即将要运行的jvm指令码对应的地址,或者说行号位置。
上述代码中每个指令码前面都有一个行号,你就可以把它看作当前线程执行到某一行代码位置的一个标识,这个值就是程序计数器的值。
那么jvm虚拟机为什么要设置程序计数器这个结构呢?就是为了多线程的出现,多线程之间的切换,当一个程序被挂起的时候,总是要恢复的,那么恢复到哪个位置呢,总不能又重新开始执行吧,那么程序计数器就解决了这个问题。
3.方法区
在jdk1.8之前,有一个名称叫做持久带/永久代,很多同学应该听过,在jdk1.8之后,oracle官方改名为元空间。存放常量、静态变量、类元信息。public static int initData = 666;
这个initData就是静态变量,毋庸置疑是存放在方法区的
public static User user = new User();
那么这个user就有点不一样了,user变量放在方法区,new的User是存放在堆中的
到这里我们就能意识到栈,堆,方法区之间都是有联系的。
栈中的局部变量,方法区中的静态变量,如果是对象类型的话都会指向堆中new出来中的对象,那么红色的联系代表什么呢?我们先来了解一下对象。
对象组成
你对对象的了解有多少呢,天天用对象,你是否知道对象在虚拟机中的存储结构呢?
对象在内存中存储的布局可以分为3块区域:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)。下图是普通对象实例与数组对象实例的数据结构:
对象头
HotSpot虚拟机的对象头包括两部分信息:
Mark Word
第一部分markword,用于存储对象自身的运行时数据,如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等,这部分数据的长度在32位和64位的虚拟机(未开启压缩指针)中分别为32bit和64bit,官方称它为“MarkWord”。Klass Pointer
对象头的另外一部分是klass类型指针,即对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例.数组长度(只有数组对象有)
如果对象是一个数组, 那在对象头中还必须有一块数据用于记录数组长度.实例数据
实例数据部分是对象真正存储的有效信息,也是在程序代码中所定义的各种类型的字段内容。无论是从父类继承下来的,还是在子类中定义的,都需要记录起来。
对齐填充第三部分对齐填充并不是必然存在的,也没有特别的含义,它仅仅起着占位符的作用。由于HotSpot VM的自动内存管理系统要求对象起始地址必须是8字节的整数倍,换句话说,就是对象的大小必须是8字节的整数倍。而对象头部分正好是8字节的倍数(1倍或者2倍),因此,当对象实例数据部分没有对齐时,就需要通过对齐填充来补全。
其中的klass类型指针就是那条红色的联系,那是怎么联系的呢?
类加载其实最终是以类元信息的形式存储在方法区中的,math和math2都是由同一个类new出来的,当对象被new时,都会在对象头中存储一个指向类元信息的指针,这就是Klass Pointer.
到这里我们就讲解了栈,程序计数器和方法区,下面我们简单介绍一下本地方法区,最后再终点讲解堆。
4.本地方法栈
实际上现在本地方法栈已经用的比较少了,大家应该都有听过本地方法吧
如何经常用的线程类
new Thread().start();
public synchronized void start() { if (threadStatus != 0) throw new IllegalThreadStateException(); group.add(this); boolean started = false; try { start0(); started = true; } finally { try { if (!started) { group.threadStartFailed(this); } } catch (Throwable ignore) { } } }
其中底层调用了一个start0()的方法
private native void start0();
这个方法没有实现,但又不是接口,是使用native修饰的,是属于本地方法,底层通过C语言实现的,那java代码里为什么会有C语言实现的本地方法呢?
大家都知道JAVA是问世的,在那之前一个公司的系统百分之九十九都是使用C语言实现的,但是java出现后,很多项目都要转为java开发,那么新系统和旧系统就免不了要有交互,那么就需要本地方法来实现了,底层是调用C语言中的dll库文件,就类似于java中的jar包,当然,如今跨语言的交互方式就很多了,比如thrift,http接口方式,webservice等,当时并没有这些方式,就只能通过本地方法来实现了。
那么本地方法始终也是方法,每个线程在运行的时候,如果有运行到本地方法,那么必然也要产生局部变量等,那么就需要存储在本地方法栈了。如果没有本地方法,也就没有本地方法栈了。
5.堆
最后我们讲堆,堆是最重要的一块内存区域,我相信大部分人对堆都不陌生。但是对于它的内部结构,运作细节想要搞清楚也没那么简单。
对于这个基本组成大家应该都有所了解,对就是由年轻代和老年代组成,年轻代又分为伊甸园区和survivor区,survivor区中又有from区和to区.
我们new出来的对象大家都知道是放在堆中,那具体放在堆中的哪个位置呢?
其实new出来的对象一般都放在Eden区,那么为什么叫伊甸园区呢,伊甸园就是亚当夏娃住的地方,不就是造人的地方么?所以我们new出来的对象就是放在这里的,那当Eden区满了之后呢?
假设我们给对分配600M内存,这个是可以通过参数调节的,我们后文再讲。那么老年代默认是占2/3的,也就是差不多400M,那年轻代就是200M,Eden区160M,Survivor区40M。
GC
一个程序只要在运行,那么就不会不停的new对象,那么总有一刻Eden区会放满,那么一旦Eden区被放满之后,虚拟机会干什么呢?没错,就是gc,不过这里的gc属于minor gc,就是垃圾收集,来收集垃圾对象并清理的,那么什么是垃圾对象呢?
好比我们上面说的math对象,我们假设我们是一个web应用程序,main线程执行完之后程序不会结束,但是main方法结束了,那么main()方法栈帧会被释放,局部变量会被释放,但是局部变量对应的堆中的对象还是依然存在的,但是又没有指针指向它,那么它就是一个垃圾对象,那就应该被回收掉了,之后如果还会new Math对象,也不会用这个之前的了,因为已经无法找到它了,如果留着这个对象只会占用内存,显然是不合适的。
这里就涉及到了一个GC Root根以及可达性分析算法的概念,也是面试偶尔会被问到的。
可达性分析算法是将GC Roots对象作为起点,从这些起点开始向下搜索引用的对象,找到的对象都标记为非垃圾对象,其余未标记的都是垃圾对象。
那么GC Roots根对象又是什么呢,GC Roots根就是判断一个对象是否可以回收的依据,只要能通过GC Roots根向下一直搜索能搜索到的对象,那么这个对象就不算垃圾对象,而可以作为GC Roots根的有线程栈的本地变量、静态变量、本地方法栈的变量等等它们引用的对象,说白了就是找到和根节点有联系的对象就是有用的对象,其余都认为是垃圾对象来回收。
经历了第一次minor gc后,没有被清理的对象就会被移到From区,如上图。
上面在说对象组成的时候有写到,在对象头的Mark Word中有存储GC分代年龄,一个对象每经历一次gc,那么它的gc分代年龄就会+1,如上图。
那么如果第二次新的对象又把Eden区放满了,那么又会执行minor gc,但是这次会连着From区一起gc,然后将Eden区和From区存活的对象都移到To区域,对象头中分代年龄都+1,如上图。
那么当第三次Eden区又满的时候,minor gc就是回收Eden区和To区域了,TEden区和To区域还活着的对象就会都移到From区,如上图。说白了就是Survivor区中总有一块区域是空着的,存活的对象存放是在From区和To区轮流存放,也就是互相复制拷贝,这也就是垃圾回收算法中的复制-回收算法。
如果一个对象经历了一个限值15次gc的时候,就会移至老年代。那如果还没有到限值,From区或者To区域也放不下了,就会直接挪到老年代,这只是举例了两种常规规则,还有其他规则也是会把对象存放至老年代的。
那么随着应用程序的不断运行,老年代最终也是会满的,那么此时也会gc,此时的gc就是Full gc了。
GC案例
下面我们通过一个简单的演示案例来更加清楚的了解GC。
public class HeapTest { byte[] a = new byte[1024*100]; public static void main(String[] args) throws InterruptedException { ArrayList<HeapTest> heapTest = new ArrayList<>(); while(true) { heapTest.add(new HeapTest()); Thread.sleep(10); } } }
这块代码很明显,就是一个死循环,不断的往list中添加new出来的对象。
我们这里使用jdk自带的一个jvm调优工具jvisualvm来观察一下这个代码执行的的内存结构。
运行代码打开之后我们可以看到这样的界面:
我们在左边的应用程序中可以看到我们运行的这个代码,右边是它的一些jvm,内存信息,我们这里不关注,我们需要用到的是最后一个Visual GC面板,这是一个插件,如果你的打开没有这一栏的话,可以再工具栏的插件中进行下载安装。
打开visual GC,我们先看一下界面大概的布局,
其中老年代(Olc),伊甸园区(Eden),S0(From),S1(To)几个区域的内存和动态分配图都是清晰可见,以一对应的。
我们选择中间一张图给大家对应一下上面所讲的内容:
1:对象放入Eden区
2:Eden区满发生minor gc
3:第二步的存活对象移至From(Survivor 0)区
4:Eden区再满发生minor gc
5:第四步存活的对象移至To(Survivor 1)区
这里可以注意到From和To区域和我们上面所说移至,总有一个是空的。
大家还可以注意到老年代这里,都是一段一段的直线,中间是突然的增加,这就是在minor gc中一批一批符合规则的对象被批量移入老年代。
那当我们老年代满了会发生什么呢?当然是我们上面说过的Full GC,但是你仔细看我们写的这个程序,我们所有new出来的HeapTest对象都是存放在heapLists中的,那就会被这个局部变量所引用,那么Full GC就不会有什么垃圾对象可以回收,可是内存又满了,那怎么办?
没错,就是我们就算没见过也总听过的OOM。
到这里jvm内存模型简单介绍就结束了,看到这里还不点个赞嘛!
欢迎访问我的个人小站哦:我爱吃土豆
-
基于海洋流场的拓扑区域划分的研究
2021-01-31 21:51:54可以使用特征可视化中的拓扑结构分析法来划分拓扑区域,但这种方法太过于概括,区域大小只是相对的,没有考虑到附近临界点对周围流体运动的影响。还可以使用Voronoi图来划分拓扑区域,但是该方法对于相距较近的临界... -
井下WLAN位置指纹定位中改进区域划分方法研究
2020-05-02 17:39:21提出了一种基于类关系的K-Means(CRK-Means)算法,该算法以类内离散度和类间离散度的比值为目标函数,通过使该比值最小的聚类的聚合、分离过程即可得到避免了奇点问题的最优聚类,完成定位区域的合理划分。... -
JVM的内存区域划分-- 堆、栈、方法区、本地方法栈、程序计数器
2018-07-30 15:24:03JVM的内存区域划分-- 堆、栈、方法区、本地方法栈、程序计数器 JVM的内存区域划分 JVM的内存区域划分 学过C语言的朋友都知道C编译器在划分内存区域的时候经常将管理的区域划分为数据段和代码段,数据段...JVM的内存区域划分-- 堆、栈、方法区、本地方法栈、程序计数器
JVM的内存区域划分
JVM的内存区域划分
学过C语言的朋友都知道C编译器在划分内存区域的时候经常将管理的区域划分为数据段和代码段,数据段包括堆、栈以及静态数据区。那么在Java语言当中,内存又是如何划分的呢?
由于Java程序是交由JVM执行的,所以我们在谈Java内存区域划分的时候事实上是指JVM内存区域划分。在讨论JVM内存区域划分之前,先来看一下Java程序具体执行的过程:
如上图所示,首先Java源代码文件(.java后缀)会被Java编译器编译为字节码文件(.class后缀),然后由JVM中的类加载器加载各个类的字节码文件,加载完毕之后,交由JVM执行引擎执行。在整个程序执行过程中,JVM会用一段空间来存储程序执行期间需要用到的数据和相关信息,这段空间一般被称作为Runtime Data Area(运行时数据区),也就是我们常说的JVM内存。因此,在Java中我们常常说到的内存管理就是针对这段空间进行管理(如何分配和回收内存空间)。
在知道了JVM内存是什么东西之后,下面我们就来讨论一下这段空间具体是如何划分区域的,是不是也像C语言中一样也存在栈和堆呢?
一.运行时数据区包括哪几部分?
根据《Java虚拟机规范》的规定,运行时数据区通常包括这几个部分:程序计数器(Program Counter Register)、Java栈(VM Stack)、本地方法栈(Native Method Stack)、方法区(Method Area)、堆(Heap)。
如上图所示,JVM中的运行时数据区应该包括这些部分。在JVM规范中虽然规定了程序在执行期间运行时数据区应该包括这几部分,但是至于具体如何实现并没有做出规定,不同的虚拟机厂商可以有不同的实现方式。
二.运行时数据区的每部分到底存储了哪些数据?
下面我们来了解一下运行时数据区的每部分具体用来存储程序执行过程中的哪些数据。
1.程序计数器
程序计数器(Program Counter Register),也有称作为PC寄存器。想必学过汇编语言的朋友对程序计数器这个概念并不陌生,在汇编语言中,程序计数器是指CPU中的寄存器,它保存的是程序当前执行的指令的地址(也可以说保存下一条指令的所在存储单元的地址),当CPU需要执行指令时,需要从程序计数器中得到当前需要执行的指令所在存储单元的地址,然后根据得到的地址获取到指令,在得到指令之后,程序计数器便自动加1或者根据转移指针得到下一条指令的地址,如此循环,直至执行完所有的指令。
虽然JVM中的程序计数器并不像汇编语言中的程序计数器一样是物理概念上的CPU寄存器,但是JVM中的程序计数器的功能跟汇编语言中的程序计数器的功能在逻辑上是等同的,也就是说是用来指示 执行哪条指令的。
由于在JVM中,多线程是通过线程轮流切换来获得CPU执行时间的,因此,在任一具体时刻,一个CPU的内核只会执行一条线程中的指令,因此,为了能够使得每个线程都在线程切换后能够恢复在切换之前的程序执行位置,每个线程都需要有自己独立的程序计数器,并且不能互相被干扰,否则就会影响到程序的正常执行次序。因此,可以这么说,程序计数器是每个线程所私有的。
在JVM规范中规定,如果线程执行的是非native方法,则程序计数器中保存的是当前需要执行的指令的地址;如果线程执行的是native方法,则程序计数器中的值是undefined。
由于程序计数器中存储的数据所占空间的大小不会随程序的执行而发生改变,因此,对于程序计数器是不会发生内存溢出现象(OutOfMemory)的。
2.Java栈
Java栈也称作虚拟机栈(Java Vitual Machine Stack),也就是我们常常所说的栈,跟C语言的数据段中的栈类似。事实上,Java栈是Java方法执行的内存模型。为什么这么说呢?下面就来解释一下其中的原因。
Java栈中存放的是一个个的栈帧,每个栈帧对应一个被调用的方法,在栈帧中包括局部变量表(Local Variables)、操作数栈(Operand Stack)、指向当前方法所属的类的运行时常量池(运行时常量池的概念在方法区部分会谈到)的引用(Reference to runtime constant pool)、方法返回地址(Return Address)和一些额外的附加信息。当线程执行一个方法时,就会随之创建一个对应的栈帧,并将建立的栈帧压栈。当方法执行完毕之后,便会将栈帧出栈。因此可知,线程当前执行的方法所对应的栈帧必定位于Java栈的顶部。讲到这里,大家就应该会明白为什么 在 使用 递归方法的时候容易导致栈内存溢出的现象了以及为什么栈区的空间不用程序员去管理了(当然在Java中,程序员基本不用关系到内存分配和释放的事情,因为Java有自己的垃圾回收机制),这部分空间的分配和释放都是由系统自动实施的。对于所有的程序设计语言来说,栈这部分空间对程序员来说是不透明的。下图表示了一个Java栈的模型:
局部变量表,顾名思义,想必不用解释大家应该明白它的作用了吧。就是用来存储方法中的局部变量(包括在方法中声明的非静态变量以及函数形参)。对于基本数据类型的变量,则直接存储它的值,对于引用类型的变量,则存的是指向对象的引用。局部变量表的大小在编译器就可以确定其大小了,因此在程序执行期间局部变量表的大小是不会改变的。
操作数栈,想必学过数据结构中的栈的朋友想必对表达式求值问题不会陌生,栈最典型的一个应用就是用来对表达式求值。想想一个线程执行方法的过程中,实际上就是不断执行语句的过程,而归根到底就是进行计算的过程。因此可以这么说,程序中的所有计算过程都是在借助于操作数栈来完成的。
指向运行时常量池的引用,因为在方法执行的过程中有可能需要用到类中的常量,所以必须要有一个引用指向运行时常量。
方法返回地址,当一个方法执行完毕之后,要返回之前调用它的地方,因此在栈帧中必须保存一个方法返回地址。
由于每个线程正在执行的方法可能不同,因此每个线程都会有一个自己的Java栈,互不干扰。
3.本地方法栈
本地方法栈与Java栈的作用和原理非常相似。区别只不过是Java栈是为执行Java方法服务的,而本地方法栈则是为执行本地方法(Native Method)服务的。在JVM规范中,并没有对本地方发展的具体实现方法以及数据结构作强制规定,虚拟机可以自由实现它。在HotSopt虚拟机中直接就把本地方法栈和Java栈合二为一。
4.堆
在C语言中,堆这部分空间是唯一一个程序员可以管理的内存区域。程序员可以通过malloc函数和free函数在堆上申请和释放空间。那么在Java中是怎么样的呢?
Java中的堆是用来存储对象本身的以及数组(当然,数组引用是存放在Java栈中的)。只不过和C语言中的不同,在Java中,程序员基本不用去关心空间释放的问题,Java的垃圾回收机制会自动进行处理。因此这部分空间也是Java垃圾收集器管理的主要区域。另外,堆是被所有线程共享的,在JVM中只有一个堆。
5.方法区
方法区在JVM中也是一个非常重要的区域,它与堆一样,是被线程共享的区域。在方法区中,存储了每个类的信息(包括类的名称、方法信息、字段信息)、静态变量、常量以及编译器编译后的代码等。
在Class文件中除了类的字段、方法、接口等描述信息外,还有一项信息是常量池,用来存储编译期间生成的字面量和符号引用。
在方法区中有一个非常重要的部分就是运行时常量池,它是每一个类或接口的常量池的运行时表示形式,在类和接口被加载到JVM后,对应的运行时常量池就被创建出来。当然并非Class文件常量池中的内容才能进入运行时常量池,在运行期间也可将新的常量放入运行时常量池中,比如String的intern方法。
在JVM规范中,没有强制要求方法区必须实现垃圾回收。很多人习惯将方法区称为“永久代”,是因为HotSpot虚拟机以永久代来实现方法区,从而JVM的垃圾收集器可以像管理堆区一样管理这部分区域,从而不需要专门为这部分设计垃圾回收机制。不过自从JDK7之后,Hotspot虚拟机便将运行时常量池从永久代移除了。
以上为个人看法和观点,如有不正之处希望谅解并欢迎指正。
参考资料:
http://blog.csdn.net/ns_code/article/details/17565503
http://www.cnblogs.com/sunada2005/p/3577799.html
《深入理解Java虚拟机》
《Java虚拟机规范 SE7》
-
论文研究-一种区域递归划分的图像插值方法 .pdf
2019-08-15 14:59:55一种区域递归划分的图像插值方法,卢志茂,,Ncut (Normalied cut)是一种基于图论的规范化的图像分割准则,它可以融合图像的不同特征,同时得到不同的区域集合之间的差异性和同一区� -
Java虚拟机的内存区域划分
2020-12-22 17:10:08Java虚拟机在执行Java程序的过程中会把它所管理的内存划分成很多个不同的数据区域。这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则是依赖用户线程的启动和结束而... -
java运行时区域划分(方法区,运行时常量)
2019-03-06 16:25:061>方法区:与堆内存一样,是各个线程共享的内存区域,它用于存储已经虚拟机加载的类信息,静态变量,即是... java中对java的方法区的限制非常宽松,除了和java堆一样不需要连续的内存空间和可以选择固定大小或者扩...1>方法区:与堆内存一样,是各个线程共享的内存区域,它用于存储已经虚拟机加载的类信息,静态变量,即是编译器编译后的代码等数据,虽然java虚拟机规范把方法区域描述为堆的一个逻辑部分,但是它却有意个别名,叫做Non-Heap(非堆),目的是为了将java堆和方法区区分开来.
java中对java的方法区的限制非常宽松,除了和java堆一样不需要连续的内存空间和可以选择固定大小或者扩展外,还可以选择不事先垃圾收集,相对而言,垃圾收集器在方法区的行为还是比较少的。在方法区的内存回收主要是针对常量池的回收和对类型的卸载,相对来说,对于方法区的垃圾回收成绩比较令人难以满意,尤其是对类型的卸载,对性能的优化并不友好.在java虚拟机规范中,当方法区无法满足内存分配需求时候,将抛出outofmemoryerror异常
1.2>运行时常量池
运行时常量池是方法区的一部分,用于存储编译期间生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中存放,java虚拟机在常量池没有左任何要求,只会区保存class文件中描述的符号引用,还会把翻译出来的直接引用也存储在运行时常量池里面.,运行时常量池也是方法区的一个部分,其也会受到内存的限制,当常量池无法在申请到内存空间的时候,就会抛出Outofmemoryerror异常
-
JVM的内存区域划分
2017-10-18 17:51:42JVM的内存区域划分,包括程序计数器、Java栈、本地方法栈、堆、方法区 -
Java内存区域怎么划分的?
2020-09-18 15:12:57Java内存区域怎么划分的? 运行时数据区域包含以下五个区域:程序计数器,Java虚拟机栈,本地方法栈,堆,方法区(其中前三个区域各线程私有,相互独立,后面两个区域所有线程共享) 线程私用的部分(Java虚拟机栈,... -
区域划分及LSA的种类
2020-05-18 19:37:45区域划分:把网络分成较小的块或区域 内部路由器:所有接口都在同一区域 如R 3 区域边界路由器(ABR):接口属于不同的区域 如R1,R2,R4,R5 骨干路由器:所有的ABR和骨干区域中的内部路由器 AS边界路由器(ASBR):与... -
vue 组件分区域显示_Vue.js划分组件的方法
2021-01-17 13:34:31总结下来有两种可以划分,两种划分的方法一种是页面上的功能块,select,pagenation,和一些需要大量代码去实现的一些部分,我们可以把它提取出来放到一起或者分类。还有一种根据页面区域来划分,h... -
基于区域划分的快速图像插值算法
2020-10-17 16:54:54图像插值是将低分辨率图像放大后提高视觉效果的有效方法,传统...为克服以上缺陷,提出了一种先将图像进行区域划分,然后再进行快速图像插值的算法,既保证了算法较低的复杂度,又优化了图像显示效果,适合实际应用。 -
基于区域划分的煤矿井下无线传感器网络定位算法
2020-05-05 19:15:13针对这一问题提出了一种在无线传感器网络中基于区域划分的定位算法。该算法在修正加权质心定位算法的基础上,通过将锚节点组成区域划分为更小的区域,使未知节点所处区域更加明确的方法来提高定位精度。仿真结果表明,... -
JVM 区域划分
2019-09-24 10:12:10JVM 区域划分 程序计数器 Java虚拟机栈 Java堆内存 方法区 / Metaspace 本地方法栈 堆外内存 全文总结 ================================================ 1:JVM 区域划分 jvm的区域,大致有以下几块: 程序计数器 ... -
JVM区域划分
2019-09-29 03:11:24JVM的区域划分主要包括以下部分: 堆 方法区 程序计数器 虚拟机栈 本地方法区 在上述的几个部分里,堆和方法区是线程共享的,也就是说一个JVM虚拟机里出的一个公共的区域,所有的线程... -
基于子区域划分的室内定位算法研究
2021-01-27 14:21:44文中基于提高射频识别定位系统中定位精度的目的,提出了一种改进的IMLANDMARC算法,该算法通过对待定位标签所在区域进行子区域划分,并增加虚拟参考标签的方法,对LANDMARC算法进行改进,使用Matlab软件对算法进行... -
java内存区域划分(堆,栈,方法区)
2020-09-23 10:45:04java虚拟机在执行java程序的过程中会把它所管理的内存划分成若干个不同的数据区域。这些区域各有用途,以及创建和销毁的时间。有的区域随着虚拟机的进程的启动而存在,有的则依赖用户线程的启动和结束而建立和销毁。... -
JVM的区域划分以及工作原理
2019-04-24 10:28:32jvm的区域划分如下所示: 大致就是分为:程序计数器,虚拟机栈,堆,方法区,本地方法栈,这几个部分。 接下来我们从自己写好的Java代码如何通过JVM来运行的角度,来分析一下JVM里这些区域是如何支撑我们的Java代码... -
jvm数据区域划分(堆,栈,方法区)
2018-11-22 20:48:48jvm数据区域划分 jvm其实是java运行时的数据区域。具体划分如下: 说一下各个划分的区域的功能。 执行引擎:执行引擎可以理解为程序执行的入口,比如操作系统有一个个的小图标,我们点击图标之后,就会执行 ...