我在Linux下运行的Java应用程序有问题.
当我使用默认的最大堆大小(64 MB)启动应用程序时,我看到使用tops应用程序为应用程序分配了240 MB的虚拟内存.这会在计算机上创建一些其他软件的问题,这些软件相对资源有限.
据我所知,无论如何都不会使用保留的虚拟内存,因为一旦达到堆限制OutOfMemoryError就会被抛出.我在Windows下运行相同的应用程序,我发现虚拟内存大小和堆大小相似.
无论如何我可以在Linux下配置用于Java进程的虚拟内存吗?
编辑1:问题不在于堆.问题是,如果我设置一个128 MB的堆,那么Linux仍然会分配210 MB的虚拟内存,这是不需要的.**
编辑2:使用ulimit -v允许限制虚拟内存量.如果大小设置低于204 MB,则应用程序将不会运行,即使它不需要204 MB,只需64 MB.所以我想了解为什么Java需要这么多虚拟内存.这可以改变吗?
编辑3:系统中运行了几个其他应用程序,它们是嵌入式的.系统确实有虚拟内存限制(来自评论,重要细节).
我想创建一个程序来模拟Unix服务器上的内存不足(OOM)情况.我创造了这个超级简单的记忆食者:
#include <stdio.h>
#include <stdlib.h>
unsigned long long memory_to_eat = 1024 * 50000;
size_t eaten_memory = 0;
void *memory = NULL;
int eat_kilobyte()
{
memory = realloc(memory, (eaten_memory * 1024) + 1024);
if (memory == NULL)
{
// realloc failed here - we probably can't allocate more memory for whatever reason
return 1;
}
else
{
eaten_memory++;
return 0;
}
}
int main(int argc, char **argv)
{
printf("I will try to eat %i kb of ram\n", memory_to_eat);
int megabyte = …Run Code Online (Sandbox Code Playgroud) 我经常对操作系统中的虚拟化概念感到困惑.考虑将RAM作为物理内存,为什么我们需要虚拟内存来执行进程?
当来自外部硬盘驱动器的进程(程序)被带到主存储器(物理存储器)以执行时,该虚拟存储器在哪里.
谁负责虚拟内存以及虚拟内存的大小?
假设RAM的大小是4GB(即2 ^ 32-1地址空间),虚拟内存的大小是多少?
virtualization ram operating-system memory-management virtual-memory
在一本书中,我读了以下内容:
32位处理器具有2 ^ 32个可能的地址,而当前的64位处理器具有48位地址空间
我的期望是,如果它是一个64位处理器,地址空间也应该是2 ^ 64.
所以我想知道这种限制的原因是什么?
x86-64 cpu-architecture virtual-memory processor-architecture
这个问题旨在填补关于该主题的良好免费信息的真空.
我相信一个好的答案将适合一个大的答案或至少在几个答案.
主要目标是为完整的初学者提供足够的信息,以便他们可以自己学习手册,并能够理解与分页相关的基本操作系统概念.
建议的指导方针:
相关问题以及为什么我认为它们不是愚蠢的:
x86页表如何工作?:标题与此问题几乎相同,但是正文询问与cr3和TLB相关的具体问题.那个问题是这个问题的一个子集.
x86虚拟化如何工作:正文仅询问源.
在我们的生产机器上运行一个简单的Java程序,我注意到这个程序占用了更多的10G virt.我知道虚拟内存不是那么相关,但至少我想了解为什么需要它.
public class Main {
public static void main(String[] args) {
System.out.println("Hello World!");
try {
Thread.sleep(10000);
} catch(InterruptedException e) {
/* ignored */
}
}
}
Run Code Online (Sandbox Code Playgroud)
top当我运行那个小程序时,这是什么意思:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
18764 myuser 20 0 10.2g 20m 8128 S 1.7 0.1 0:00.05 java
Run Code Online (Sandbox Code Playgroud)
有谁知道为什么会这样?
uname -a说:
Linux m4fxhpsrm1dg 2.6.32-358.18.1.el6.x86_64 #1 SMP Fri Aug 2 17:04:38 EDT 2013 x86_64 x86_64 x86_64 GNU/Linux
Run Code Online (Sandbox Code Playgroud)
在较旧的32bit-linux机器上,同一程序仅消耗大约1G的virt.旧机器有4GB RAM,新机器有32GB.
每个进程都有自己的页表,还是只是将页面条目添加到一个大页表中?
operating-system memory-management virtual-memory page-tables
我试图了解多级页表如何节省内存.根据我的理解,多级页表总共消耗比单级页表更多的内存.
示例:考虑页面大小为64KB且32位处理器的内存系统.页表中的每个条目都是4个字节.
单级页表:表示页面偏移需要16(2 ^ 16 = 64KB)位.所以休息16位用于索引到页表.所以
*页面大小= 2 ^ 16(页数)*4字节(每页表项的大小)= 2 ^ 18字节*
多级页表:在两级页表的情况下,让我们使用前10个最高位来索引到第一级页表.接下来10位索引到第二级页表,其具有页码到帧号映射.其余12位表示页面偏移量.
第二级页表的大小= 2 ^ 10(条目数)*4字节(每个条目的大小)= 4 KB
所有二级页表的总大小= 2 ^ 10(二级页表的数量)*4KB(每个二级页表的大小)= 4 MB
第一级页表的大小= 2 ^ 10(条目数)*(10/8)字节(每个条目的大小)= 1.25 KB
存储第一级和第二级页表所需的总内存= 4 MB + 1.25 KB
因此我们需要更多内存来存储多级页表.
如果是这种情况,多级页表如何节省内存空间?
我想知道提交大小(在任务管理器中可见)和虚拟大小(在SysInternals的Process Explorer中可见)之间的确切区别.
Process Explorer中的Virtual Size参数看起来更准确地指示进程的总虚拟内存使用情况.但是,提交大小始终小于虚拟大小,我想它不包括进程使用的所有虚拟内存.我希望有人解释这些参数中包含的内容.
我一直在学习这些主题并阅读了许多文章和书籍,但他们都缺乏一些补充信息,让我更加困惑.所以在这里,我想在我提出问题时解释我所知道的.希望这个主题对我这样的人有用.如果有必要,我还想学习我的知识和更正的有效性.
虚拟内存
有些文章说"虚拟内存是硬盘的一些空间,模拟物理内存,这样我们就可以拥有比实际更多的内存." 其他一些文章说"虚拟内存是物理内存(RAM)的组合,硬盘的一部分就像物理内存和页面表."然而它们是不同的东西,我不明白为什么有这样的不同解释.
让我们来看第二个解释,因为维基百科也是如何描述虚拟内存的.此时虚拟地址是有意义的,因为我们直接使用虚拟内存中的地址而不是物理内存.
顺便说一句,我的Mac说我有8GB的物理内存和8GB的虚拟内存.在这种情况下,VM是否包含物理内存,还是HD用作内存的空间量?我的程序有16GB内存吗?

问题1:
Intel i5具有36位地址总线,这意味着您可以寻址64GB内存.假设我在我的电脑上安装了4GB RAM.但是,我的程序可能不知道所安装内存的大小,因为它将在具有不同内存大小的许多不同系统上使用.这就是虚拟内存变得方便的地方.它抽象出安装的内存的实际大小.
但是,当我的程序想要访问内存地址0xFFFFFFFFF时会发生什么?我只安装了4GB,也许还有一些高清内存空间.
我对这个问题有两个理论:
1.由于页面表由操作系统维护,操作系统对该地址进行解码,找出哪个页面并检查页面表中的页面,看看它们是否有与之关联的物理地址(有效和无效标志),如果是然后转到虚拟地址中定义的物理内存+偏移量中的页面入口点的物理地址并带来该值.否则会发生页面错误,操作系统在辅助存储中查找该页面,获取它并将其放入内存并更新页面表.
2.它抛出OutOfMemory类型的异常,表示我没有任何给定地址可以解决的内存.
第一个理论的缺点是当程序想要使用64GB内存时会发生什么?然后我们需要有60GB的高清内存空间,因为我们只有4GB.但是,在屏幕截图下面MAC告诉我,只有8GB的虚拟内存.
问题2:
进程如何放入虚拟内存?我的意思是每个进程都有可用的0x0 - 0xFFFFFFFFF虚拟内存空间,或者只有一个虚拟内存地址空间可以放置所有进程吗?
如果每个进程都假定它们具有可用的所有内存,则内存如下所示:

如果只有一个虚拟内存概念,那么它将如下所示:

页表
因此,页表是位于物理地址和虚拟地址之间的数据结构.它是一个关联数组(或类似字典),对于每个页面(键),都有一个物理地址关联(值).
OS使用MMU(内存管理单元)执行从虚拟地址到物理地址的转换.

问题3:
是否有一个巨大的巨型页面表,其中包含每个进程的所有页面,或者每个进程都有自己的页面表?
分页
分页是一种内存管理方法.虚拟内存和物理内存由内存管理单元分为页面(固定和相同大小的块).当您在内存和辅助存储之间交换页面时,此技术非常有用,以便您可以在它们之间交换页面.例如,您的程序请求位于地址中的数据.但是,程序使用的地址是虚拟地址,MMU使用页表对其进行转换.在此期间,MMU检查页表是否在页表中存在所请求的内容,如果不是,则OS从辅助存储器获取它并更新页表.
问题4:
假设一个进程从一个地址请求数据,该地址被转换为已经有一些数据的物理地址.如何知道数据不属于请求者进程,应该替换为辅助存储中的数据?
例如,有脏位用于是否将该页面写回硬盘,但我不认为这是决定所有者进程的原因.