GVKun编程网logo

Java使用的内存比分配的内存更多(java使用的内存比分配的内存更多吗)

4

如果您想了解Java使用的内存比分配的内存更多的相关知识,那么本文是一篇不可错过的文章,我们将对java使用的内存比分配的内存更多吗进行全面详尽的解释,并且为您提供关于c–使用malloc分配比存在更

如果您想了解Java使用的内存比分配的内存更多的相关知识,那么本文是一篇不可错过的文章,我们将对java使用的内存比分配的内存更多吗进行全面详尽的解释,并且为您提供关于c – 使用malloc分配比存在更多的内存、c – 使用由不同分配器分配的内存、c – 容器使用的内部类型的内存分配、c – 释放动态分配的内存的有价值的信息。

本文目录一览:

Java使用的内存比分配的内存更多(java使用的内存比分配的内存更多吗)

Java使用的内存比分配的内存更多(java使用的内存比分配的内存更多吗)

使用以下Java选项启动Apache Tomcat(Atlassian Confluence)实例:

JAVA_OPTS="-Xms256m -Xmx512m -XX:MaxPermSize=256m -Djava.awt.headless=true "

但是,我看到启动后,它很快就耗尽了虚拟服务器上可用的1GB内存中的大部分。

 PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
 6082 root      19   0 1105m 760m  16m S  0.7 74.2   5:20.51 java

总消耗的内存(堆+ PermGen)是否不应该保持在使用-
Xmx指定的值以下?这引起的问题之一是我无法使用关闭脚本关闭服务器,因为它试图生成具有256MB内存的JVM,该JVM因不可用而失败。

c – 使用malloc分配比存在更多的内存

c – 使用malloc分配比存在更多的内存

每次从stdin读取字母’u’时,此代码段将分配2Gb,并在读取’a’时初始化所有已分配的字符.

#include dio.h>
#include 

我在具有3Gb内存的Linux虚拟机上运行此代码.在使用htop工具监视系统资源使用情况时,我意识到malloc操作没有反映在资源上.

例如,当我只输入’u’一次(即分配2GB的堆内存)时,我看不到内存使用量在htop中增加了2GB.只有当我输入’a'(即初始化)时,我才会看到内存使用量的增加.

因此,我能够“malloc”存在比存在更多的堆内存.例如,我可以使用malloc 6GB(比我的内存和交换内存更多)和malloc允许它(即malloc不返回NULL).但是当我尝试初始化分配的内存时,我可以看到内存和交换内存填满,直到进程被终止.

– 我的问题:

这是一个内核错误吗?

有人可以向我解释为什么允许这种行为?

最佳答案
它被称为memory overcommit.您可以通过以root身份运行来禁用它:

 echo 2 > /proc/sys/vm/overcommit_memory

它不是我喜欢的内核功能(所以我总是禁用它).见malloc(3)和mmap(2)和proc(5)

注意:经常回声0而不是回声2但是也不总是有效.阅读文档(特别是我刚刚链接到的proc手册页).

c – 使用由不同分配器分配的内存

c – 使用由不同分配器分配的内存

假设我有一个名为vector的类,它维护一些由std :: allocator< T>分配的T类型的内部动态数组.现在,我构造了一个U类型的向量,后来想要使用移动语义,这样我就可以将它所消耗的内存用于T类型的向量,如下所示:

vector<unsigned> u(512);
// Do something with v.
vector<double> t = std::move(u);
// Do something with t.
// Later,t gets destroyed.

在t的移动构造函数中使用由u的分配器分配的内存,然后使用t的分配器解除分配它是否安全?如果是这样,我需要做些什么才能确保此操作安全?我猜我应该首先使用u的分配器为你内部数组的每个元素调用allocator.destroy().

解决方法

是的,这是STL的目的设计之一,由一个分配器分配的内存可以被另一个分配器解除分配.这是因为他们希望能够在容器之间交换元素(例如使用list :: splice),而无需对其分配器执行任何操作.这是(原因之一)为什么你不能真正拥有有状态的分配器.

c – 容器使用的内部类型的内存分配

c – 容器使用的内部类型的内存分配

C 11标准在一般集装箱要求中有以下几行.

(23.2.1 – 3)

For the components affected by this subclause that declare an allocator_type,objects stored in these components shall be constructed using the allocator_traits::construct function and destroyed using the allocator_traits::destroy function (20.6.8.2). These functions are called only for the container’s element type,not for internal types used by the container

(23.2.1 – 7)

Unless otherwise specified,all containers defined in this clause obtain memory using an allocator

是否真的,容器使用的所有内存都是由指定的分配器分配的?因为标准说内部类型不是用allocator_traits :: construct构造的,所以应该对operator new进行某种调用.但是标准也说这个子句中定义的所有容器都使用分配器来获取内存,在我看来这意味着它不能是普通的新运算符,它必须是放置新的运算符.我对么?

让我举个例子,为什么这很重要.

假设我们有一个类,它包含一些已分配的内存:

#include <unordered_map>
#include <iostream>
#include <cstdint>
#include <limits>
#include <memory>
#include <new>

class Arena
{
public:
        Arena(std::size_t size)
        {
                size_     = size;
                location_ = 0;

                data_ = nullptr;
                if(size_ > 0)
                        data_ = new(std::nothrow) uint8_t[size_];
        }
        Arena(const Arena& other) = delete;
        ~Arena()
        {
                if(data_ != nullptr)
                        delete[] data_;
        }
        Arena& operator =(const Arena& arena) = delete;

        uint8_t* allocate(std::size_t size)
        {
                if(data_ == nullptr)
                        throw std::bad_alloc();

                if((location_ + size) >= size_)
                        throw std::bad_alloc();

                uint8_t* result = &data_[location_];
                location_ += size;
                return result;
        }

        void clear()
        {
                location_ = 0;
        }

        std::size_t getNumBytesUsed() const
        {
                return location_;
        }

private:
        uint8_t* data_;
        std::size_t location_,size_;

};

我们也有自定义分配器:

template <class T> class FastAllocator
{
public:
        typedef T value_type;

        typedef T*       pointer;
        typedef const T* const_pointer;

        typedef T&       reference;
        typedef const T& const_reference;

        typedef std::size_t    size_type;
        typedef std::ptrdiff_t difference_type;

        template <class U> class rebind
        {
        public:
                typedef FastAllocator<U> other;

        };

        Arena* arena;

        FastAllocator(Arena& arena_): arena(&arena_) {}
        FastAllocator(const FastAllocator& other): arena(other.arena) {}
        template <class U> FastAllocator(const FastAllocator<U>& other): arena(other.arena) {}

        //------------------------------------------------------------------------------------
        pointer allocate(size_type n,std::allocator<void>::const_pointer)
        {
                return allocate(n);
        }
        pointer allocate(size_type n)
        {
                return reinterpret_cast<pointer>(arena->allocate(n * sizeof(T)));
        }

        //------------------------------------------------------------------------------------
        void deallocate(pointer,size_type) {}

        //------------------------------------------------------------------------------------
        size_type max_size() const
        {
                return std::numeric_limits<size_type>::max();
        }

        //------------------------------------------------------------------------------------
        void construct(pointer p,const_reference val)
        {
                ::new(static_cast<void*>(p)) T(val);
        }
        template <class U> void destroy(U* p)
        {
                p->~U();
        }

};

这就是我们使用它的方式:

typedef std::unordered_map<uint32_t,uint32_t,std::hash<uint32_t>,std::equal_to<uint32_t>,FastAllocator<std::pair<uint32_t,uint32_t>>> FastUnorderedMap;

int main()
{
        // Allocate memory in arena
        Arena arena(1024 * 1024 * 50);
        FastAllocator<uint32_t> allocator(arena);
        FastAllocator<std::pair<uint32_t,uint32_t>> pairAllocator(arena);
        FastAllocator<FastUnorderedMap> unorderedMapAllocator(arena);

        FastUnorderedMaP* fastUnorderedMap = nullptr;

        try
        {
                // allocate memory for unordered map
                fastUnorderedMap = unorderedMapAllocator.allocate(1);

                // construct unordered map
                fastUnorderedMap =
                        new(reinterpret_cast<void*>(fastUnorderedMap)) FastUnorderedMap
                        (
                                0,std::hash<uint32_t>(),std::equal_to<uint32_t>(),pairAllocator
                        );

                // insert something
                for(uint32_t i = 0; i < 1000000; ++i)
                        fastUnorderedMap->insert(std::make_pair(i,i));
        }
        catch(std::bad_alloc badAlloc)
        {
                std::cout << "--- BAD ALLOC HAPPENED DURING FAST UnorDERED MAP INSERTION ---" << std::endl;
        }

        // no destructor of unordered map is called!!!!
        return 0;
}

如您所见,unordered_map的析构函数永远不会被调用,但在破坏竞技场对象期间会释放内存.会有任何内存泄漏吗?为什么?

我真的很感激这个主题的任何帮助.

解决方法

分配器应该提供4个功能(这里感兴趣):

> 2用于内存管理:分配/解除分配
> 2用于对象生存期管理:construct / destroy

引用中的这些函数仅适用于构造和销毁(在前一句中提到),而不是分配/解除分配,因此没有矛盾.

现在,关于内存泄漏,竞技场分配器不仅应该使用竞技场分配器(容器保证)来构建容器中的对象,而且还应该从该分配器获得这些对象分配的所有内存;不幸的是,这会变得稍微复杂一些.

c – 释放动态分配的内存

c – 释放动态分配的内存

在C中,当您在堆上创建一个新变量时,如下所示:
int* a = new int;

你可以告诉C使用这样的删除来回收内存:

delete a;

但是,当程序关闭时,是否会自动释放分配了新内存的内存?

解决方法

是的,它会被自动回收,但是如果你打算编写一个大量使用堆的大型程序而不是在任何地方调用delete,你必然会快速耗尽堆内存,这会使程序崩溃.

因此,只要您不再需要所述变量,就必须仔细管理您的内存并释放动态分配的数据,并为每个新的匹配删除(如果使用new [],则删除[]).

我们今天的关于Java使用的内存比分配的内存更多java使用的内存比分配的内存更多吗的分享就到这里,谢谢您的阅读,如果想了解更多关于c – 使用malloc分配比存在更多的内存、c – 使用由不同分配器分配的内存、c – 容器使用的内部类型的内存分配、c – 释放动态分配的内存的相关信息,可以在本站进行搜索。

本文标签: