我阅读了很多关于 Java 堆的文章。我看到如果我们得到 java.lang.OutOfMemoryError 我们应该增加 -Xmx 来解决这个问题。
例如
java -Xmx2048m -Xms256m
Run Code Online (Sandbox Code Playgroud)
这会将 Java 使用的堆内存增加到 2048MB。现在谈到敲我头的问题。
参考上述设置的问题:
在调用垃圾收集器之前,Java 是否等待其 HEAP 空间达到 256MB?这是否是我们希望对 -XMx 和 -Xms 具有相同值的生产原因,以便 Java 在达到最大内存分配之前不会调用堆管理?
如果有人能提供一些关于 -Xmx 和 -Xms 的额外细节,Xmx 代表最大 Java 堆,Xms 代表最小 Java 堆,我将不胜感激。
在 Java 中,为什么String
数据类型在堆上分配内存?
我在线程对象中有一个函数,这个函数接受几个参数,我不知道当许多线程尝试使用这个函数时,这个线程是否会改变另一个线程的参数值?
我可以使用锁,但在分配参数之后。如果参数存储在堆栈中,我猜它们将位于每个线程堆栈中,但是如果它们位于堆中,如何避免线程更改另一个线程函数参数?
我已经阅读了大量帖子,但显然我在理解中遗漏了一些东西。我有一个 Tomcat 服务,它安装了:
--JvmMx=1000
--JvmMs=128
Run Code Online (Sandbox Code Playgroud)
我已经通过以下调用验证了这些设置是否成功:
PsExec.exe -s {jdk}\bin\jinfo.exe -flag MaxHeapSize {pid}
Run Code Online (Sandbox Code Playgroud)
但是,此服务的 tomcat7.exe 进程持续增长,超过此最大值的 3 倍或更多倍,直到它使服务器爬行。奇怪的是,这只是一台服务器上的问题;在其他任何地方,它都相当稳定,并保持在限制之下。我还在我的开发环境中寻找内存泄漏,但没有找到。
为了调试这个,我试过像这样强制 GC:
PsExec.exe -s {jdk}\bin\jcmd.exe {pid} GC.run
Run Code Online (Sandbox Code Playgroud)
但这似乎没有效果。所以接下来我通过将它添加到安装中来设置 jconsole 监控:
tomcat7.exe //US//%SERVICE_NAME% ++JvmOptions="-Dcom.sun.management.jmxremote"
tomcat7.exe //US//%SERVICE_NAME% ++JvmOptions="-Dcom.sun.management.jmxremote.port=8086"
tomcat7.exe //US//%SERVICE_NAME% ++JvmOptions="-Dcom.sun.management.jmxremote.ssl=false"
tomcat7.exe //US//%SERVICE_NAME% ++JvmOptions="-Dcom.sun.management.jmxremote.authenticate=false"
Run Code Online (Sandbox Code Playgroud)
现在(当然!)它很乖。GC 显然工作正常,进程内存保持在限制以下。
我很困惑。最大堆是 1 GB,永久内存是 90 MB,堆栈大小是默认的,所以大约 128 KB?而没有增长的线程数“只有”67。那么进程内存如何上升到3+GB呢?为什么它不抛出内存不足异常?
即使是现在,根据 jconsole 的“行为良好”服务仅使用大约 50 MB 的堆,在 57 个线程上运行。然而,任务管理器显示 71 个线程使用 800 MB。我认为差异是由于 Tomcat 造成的,是吗?请帮助我填补我的理解空白。
我完全理解内存的指针分配,但仅在更高级别上释放内存。我最好奇的是 C++ 如何跟踪哪些内存已经被释放?
int* ptr = new int;
cout << ptr;
delete ptr;
cout << ptr;
// still pointing to the same place however it knows you can't access it or delete it again
*ptr // BAD
delete ptr // BAD
Run Code Online (Sandbox Code Playgroud)
C++ 怎么知道我释放了那块内存。如果它只是将其转换为任意垃圾二进制数,那么当我取消引用指针时,我不会只是在读取该垃圾数吗?
相反,当然,c++ 知道这些是段错误。
那么,是否可以像这样在 C++ 中创建一个指针,并将其打印出来:
#include <iostream>
int main() {
int* ptr = new int;
(*ptr) = 3;
std::cout << ptr << '\n';
}
Run Code Online (Sandbox Code Playgroud)
然后运行它,复制 ptr 的值,并在另一个程序中,当它正在运行时,执行以下操作:
#include <iostream>
#include <cstring>
int main() {
long long pointer;
std::cin >> pointer;
int* ptr = nullptr;
std::memcpy(&ptr, &pointer, sizeof(pointer));
std::cout << *ptr << '\n';
}
Run Code Online (Sandbox Code Playgroud)
并打印出 3 个?有可能吗,或者如果没有,那究竟是为什么?
JVM Eden 空间中 TLAB 的设计让我感到困惑。我的问题是,如果对象是由 TLAB 中的一个线程分配的,那么它之后如何与其他线程共享?一个线程专有的TLAB区域会被重新组装,还是对象会被移出?
让我澄清一下:我了解 new 和 delete(和 delete[])是如何工作的。我了解堆栈是什么,并且了解何时在堆栈和堆上分配内存。
然而,我不明白的是:在堆上分配内存的位置。我知道我们应该把堆看作是一个几乎无限的 RAM 大池,但肯定不是这种情况。
什么控制选择堆内存的存储位置以及它如何选择?
另外:术语“将内存返回给操作系统”是我经常遇到的一个。这是否意味着堆在所有进程之间共享?
我之所以关心这一切,是因为我想更多地了解内存碎片。我认为在学习如何处理内存碎片之前了解堆的工作原理是个好主意,因为我没有足够的内存分配经验,也没有 C++ 直接深入研究。
c++ memory memory-management heap-memory memory-fragmentation
I have a question about triggering a destructor for an object prematurely. I have an dynamically allocated array of pointers to dynamically allocated Word objects. The name of the array is words_. words_ is a class attribute of another class called Dictionary.
In my Dictionary class, I have a function where I access each Word object and call a member function of the Word class.
The below code triggers the destructor prematurely:
Word *curr_word_ptr = words_[idx]; // This line is …
Run Code Online (Sandbox Code Playgroud) 我知道这是一个愚蠢的问题,我无法理解我是如何陷入困境的,但我在这里。在这段代码中,当我尝试在它声明的范围之外访问x 时(在堆上声明),它告诉我x 未在此范围内声明。
{
int * x = new int;
}
*x = 5; /// Error
Run Code Online (Sandbox Code Playgroud)
我以前从未遇到过这个问题。在我打电话之前x不应该存在delete x;
吗?
heap-memory ×10
memory ×6
c++ ×5
java ×3
pointers ×2
jvm ×1
memory-leaks ×1
python ×1
scope ×1
stack ×1
stack-memory ×1
string ×1
tomcat ×1