精华内容
下载资源
问答
  • 将文件上传到内存中进行传递不需要保存在本地占用内存的方法
    千次阅读
    2018-08-13 18:02:30

    通过使用ByteArrayOutputStream流将所需上传的内容写入,通过使用byteArrayOutputStream.toByteArray();方法获取内存中的数据,获取到的是byte[] 类型的数据再进行传输或者编辑

    更多相关内容
  • JVM 堆 VS 本地内存

    千次阅读 2020-05-11 16:14:13
    Java 的类实例一般在 JVM 堆上分配,而 Java 是通过 JNI 调用 C 代码来实现 Socket 通信的,那么 C 代码在运行过程中需要的内存又是从哪里分配的呢?C 代码能否直接操作 Java 堆? 为了回答这些问题,我先来说说 JVM...

    Java 的类实例一般在 JVM 堆上分配,而 Java 是通过 JNI 调用 C 代码来实现 Socket 通信的,那么 C 代码在运行过程中需要的内存又是从哪里分配的呢?C 代码能否直接操作 Java 堆?

    为了回答这些问题,我先来说说 JVM 和用户进程的关系。如果你想运行一个 Java 类文件,可以用下面的 Java 命令来执行

    java my.class
    

    这个命令行中的java其实是一个可执行程序,这个程序会创建 JVM 来加载和运行你的 Java 类。

    操作系统会创建一个进程来执行这个java可执行程序,而每个进程都有自己的虚拟地址空间,JVM 用到的内存(包括堆、栈和方法区)就是从进程的虚拟地址空间上分配的。请你注意的是,JVM 内存只是进程空间的一部分,除此之外进程空间内还有代码段、数据段、内存映射区、内核空间等。JVM 的角度看,JVM 内存之外的部分叫作本地内存,C 程序代码在运行过程中用到的内存就是本地内存中分配的。下面我们通过一张图来理解一下。
    在这里插入图片描述

    那 HeapByteBuffer 和 DirectByteBuffer 有什么区别呢?HeapByteBuffer 对象本身在 JVM 堆上分配,并且它持有的字节数组byte[]也是在 JVM 堆上分配。

    但是如果用HeapByteBuffer来接收网络数据,需要把数据从内核先拷贝到一个临时的本地内存,再从临时本地内存拷贝到 JVM 堆,而不是直接从内核拷贝到 JVM 堆上。这是为什么呢?这是因为数据从内核拷贝到 JVM 堆的过程中,JVM 可能会发生 GC,GC 过程中对象可能会被移动,也就是说 JVM 堆上的字节数组可能会被移动,这样的话 Buffer 地址就失效了。如果这中间经过本地内存中转,从本地内存到 JVM 堆的拷贝过程中 JVM 可以保证不做 GC。

    如果使用 HeapByteBuffer,你会发现 JVM 堆和内核之间多了一层中转,而 DirectByteBuffer 用来解决这个问题,DirectByteBuffer 对象本身在 JVM 堆上,但是它持有的字节数组不是从 JVM 堆上分配的,而是从本地内存分配的。

    DirectByteBuffer 对象中有个 long 类型字段 address,记录着本地内存的地址,这样在接收数据的时候,直接把这个本地内存地址传递给 C 程序,C 程序会将网络数据从内核拷贝到这个本地内存,JVM 可以直接读取这个本地内存,这种方式比 HeapByteBuffer 少了一次拷贝,因此一般来说它的速度会比 HeapByteBuffer 快好几倍。你可以通过上面的图加深理解。

    那为什么DirectByteBuffer的性能比HeapByteBuffer差依然在使用呢?
    这是因为本地内存不好管理,发生内存泄漏难以定位,从稳定性考虑,
    HeapByteBuffer更好。

    作者:taj3991
    链接:https://www.jianshu.com/p/60afb21c8876
    来源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    展开全文
  • JVM之内存模型JMM中本地内存的理解

    千次阅读 2018-05-30 14:53:32
    JMM(Java内存模型)源于物理机器CPU架构的内存模型,最初用于解决MP(多处理器架构)系统中的缓存一致性问题,而JVM为了屏蔽各个硬件平台和操作系统对内存访问机制的差异化,提出了JMM的概念。Java内存模型是一种虚拟机...

    1、JMM产生背景和定义

    JMM(Java内存模型)源于物理机器CPU架构的内存模型,最初用于解决MP(多处理器架构)系统中的缓存一致性问题,而JVM为了屏蔽各个硬件平台和操作系统对内存访问机制的差异化,提出了JMM的概念。Java内存模型是一种虚拟机规范,JMM规范了Java虚拟机与计算机内存是如何协同工作的:规定了一个线程如何和何时可以看到由其他线程修改过后的共享变量的值,以及在必须时如何同步的访问共享变量。

    2、Java内存模型和操作系统内存模型的关系

    Java内存模型和操作系统内存模型的关系
    参考文章:Java Memory Model(http://tutorials.jenkov.com/java-concurrency/java-memory-model.html) 这个英文博客讲的JMM很详细,很有参考意义

    Java内存模型的主要目标是定义程序中各个变量的访问规则。此处提到的变量只包含了实例对象、静态对象和构成数组对象的元素。局部变量和方法参数是线程私有的,不会共享,当然不存在数据竞争问题(如果局部变量是一个reference引用类型,它引用的对象在Java堆中可被各个线程共享,但是reference引用本身在Java栈的局部变量表中,是线程私有的)。为了获得较高的执行效能,Java内存模型并没有限制执行引起使用处理器的特定寄存器或者缓存来和主内存进行交互,也没有限制即时编译器进行调整代码执行顺序这类优化措施。

    JMM规定了所有的变量都存储在主内存(Main Memory)中。每个线程还有自己的工作内存(Working Memory),线程的工作内存中保存了该线程使用到的变量的主内存的副本拷贝,线程对变量的所有操作(读取、赋值等)都必须在工作内存中进行,而不能直接读写主内存中的变量(volatile变量仍然有工作内存的拷贝,但是由于它特殊的操作顺序性规定,所以看起来如同直接在主内存中读写访问一般)。不同的线程之间也无法直接访问对方工作内存中的变量,线程之间值的传递都需要通过主内存来完成。

    对于JMM与JVM本身的内存模型,参照《深入理解Java虚拟机》的解释,主内存、工作内存与Java内存区域中的Java堆、栈、方法区等并不是同一个层次的内存划分。如果两者一定要勉强对应起来,那从变量、主内存、工作内存的定义来看,主内存主要对应于Java堆中对象的实例数据部分,而工作内存则对应于虚拟机栈中的部分区域。从更低的层次来说,主内存就是硬件的内存,而为了获取更好的运行速度,虚拟机及硬件系统可能会让工作内存优先存储于寄存器和告诉缓冲中。

    3、Java内存模型的抽象结构

    在Java中,所有实例域、静态域和数组元素都存储在堆内存中,堆内存在线程之间共享(本章用“共享变量”这个术语代指实例域,静态域和数组元素)。局部变量(Local Variables),方法定义参数(Java语言规范称之为Formal Method Parameters)和异常处理器参数(Exception Handler Parameters)不会在线程之间共享,它们不会有内存可见性问题,也不受内存模型的影响。

    Java线程之间的通信由Java内存模型(本文简称为JMM)控制,JMM决定一个线程对共享变量的写入何时对另一个线程可见。从抽象的角度来看,JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存(Main Memory)中,每个线程都有一个私有的本地内存(Local Memory),本地内存中存储了该线程以读/写共享变量的副本。本地内存是JMM的一个抽象概念,并不真实存在。它涵盖了缓存、写缓冲区、寄存器以及其他的硬件和编译器优化。Java内存模型的抽象示意如图所示:
    Java内存模型

    从图来看,如果线程A与线程B之间要通信的话,必须要经历下面2个步骤。
    1)线程A把本地内存A中更新过的共享变量刷新到主内存中去。
    2)线程B到主内存中去读取线程A之前已更新过的共享变量。
    下面通过示意图来说明这两个步骤。
    这里写图片描述

    如上图所示,本地内存A和本地内存B由主内存中共享变量x的副本。假设初始时,这3个内存中的x值都为0。线程A在执行时,把更新后的x值(假设值为1)临时存放在自己的本地内存A中。当线程A和线程B需要通信时,线程A首先会把自己本地内存中修改后的x值刷新到主内存中,此时主内存中的x值变为了1。随后,线程B到主内存中去读取线程A更新后的x值,此时线程B的本地内存的x值也变为了1。从整体来看,这两个步骤实质上是线程A在向线程B发送消息,而且这个通信过程必须要经过主内存。JMM通过控制主内存与每个线程的本地内存之间的交互,来为Java程序员提供内存可见性保证。

    参考《Java并发编程的艺术》

    在这里插入图片描述

    展开全文
  • Android Studio 4.1 中的本地内存分析

    千次阅读 2021-01-13 09:30:00
    Native Memory Table (本地内存表格) 视图 从 Android Studio 4.1 Canary 6 开始,我们可以通过获取本地内存分配记录来分析为何内存未被释放。为了能够在 GPU 模拟应用上进行该项操作,我先停止正在运行的应用,...

    本文是 Android Studio 4.1 中 Profiler 有哪些新增特性的第二部分。之前的文章侧重于介绍 Android Studio 中 System Trace 的新增功能

     

    我们从大家的反馈了解到使用 C++ 调试本地内存非常困难,尤其在开发游戏的时候。在 Android Studio 4.1 中,Memory Profiler (内存分析器) 可以记录本地内存分配的调用栈。本地内存记录基于 Perfetto 后端实现,它是 Android 的新一代性能工具和问题追溯解决方案。

     

    在调试内存问题的时候,通常的做法是搞清楚什么在占用内存,什么在释放内存。本文接下来会带着大家一起使用 Native Memory Profiler 来发现内存泄漏,并且使用 GPU 模拟压力测试 (Gpu Emulation Stress Test) 作为示例工程。

    • Perfetto

      https://perfetto.dev/

    • GPU 模拟压力测试 (Gpu Emulation Stress Test)

      https://github.com/google/gpu-emulation-stress-test

    准备工作

    首先,我们从 https://github.com/google/gpu-emulation-stress-test 克隆或者下载源码。

     

    当我们发现可疑的内存泄漏时,最好的做法是从更高的层次开始并且观察系统内存的图形。您只需要在 Android Studio 中点击 profile 按钮,然后打开内存分析器,里面会显示更加详细的内存追踪信息。

    内存分析器的顶层视图,从显示中可以看到每次运行 "GPU emulation stress test" 的时候内存占用都会逐步升高

    运行了几次模拟器后,我们可以发现一些有趣的现象:

    1. 对于 GPU 模拟应用来说,GPU 内存增加是理所应当的,然而 Activity 被 finish 之后,该内存似乎被清空了。

    2. 每当我们打开 GPUEmulationStressTestActivity 的时候,本地内存都会有所增加,但是每次运行后该内存似乎并没有被重置,这就表明可能存在内存泄漏。

    Native Memory Table (本地内存表格) 视图

    从 Android Studio 4.1 Canary 6 开始,我们可以通过获取本地内存分配记录来分析为何内存未被释放。为了能够在 GPU 模拟应用上进行该项操作,我先停止正在运行的应用,然后启动分析一个新的实例。从一个初始的状态开始,会有助于我们缩小需要关注的范围,尤其是在研究一套不熟悉的代码的时候更是如此。通过内存分析器,我可以获得整个 GPU 模拟示例运行期间的本地内存分配记录。我们需要点击 Run->Profile-> ‘app’ 来重启应用。应用启动后 profile 窗口会打开,点击内存分析器,然后选择 "record native allocation"。

    本地内存记录在 Android Studio 中加载时的初始状态

    有些游戏或者应用所依赖的库会在 new 关键字之外调用 malloc 来申请内存。这个表格视图突出显示了这种情况,因而在应对这类游戏或应用时非常有用。

     

    当记录加载后,数据会以表格的形式呈现。表格中会显示调用 malloc 的叶子函数。除了显示函数名,表格里还会包含模块、调用计数、空间大小、和 delta 值。这些信息会被进行采样,因此不是所有的 malloc 或 free 的调用都会被捕捉到。这很大程度上取决于采样率,后面我们会讨论它。

     

    另外很有必要了解这些占用内存的函数是被哪些函数调用的。有两种方法可图形化该信息。第一种方法是将 "Arrange by allocation method" 选项改为 "Arrange by call stack"。表格会显示调用栈的树结构,和 CPU 记录里的类似。如果当前项目包含符号 (通常适用于可调试构建,如果您正在分析一个外部的 APK,可以参考一下文档),他们会自动被选取并启用。这样您就可以通过右键点击函数并 "Jump to source" 来直接转向源码。

    • 文档

      https://developer.android.google.cn/studio/debug/apk-debugger#attach_native

    在表格里右键点击一个元素会显示 "Jump to Source" 菜单

    内存可视化 (本地和非本地)

    我们还在内存分析器中增加了用于可视化数据的火焰图,您可以非常快速地找到分配内存最多的调用栈。该方法对于很深的调用栈非常有用。

     

    有四种方式可以在 X 轴上对数据进行排序:

    • "分配容量" (Allocation Size) 属于默认值,表示被追踪的内存总量;

    • "分配计数" (Allocation Count) 表示分配内存的对象总数;

    • "全部剩余容量" (Total Remaining Size) 表示在数据采集结束之前,整个数据采集过程中未被释放的内存容量;

    • "全部剩余计数" (Total Remaining Count) 和剩余容量类似,表示在采集结束之前,整个采集过程中未被释放的对象总数。

    采集数据加载之后,在 "全部剩余容量" 视图里,很容易发现 "lodepng" 所分配的内存容量比较大

    从这里我们可以直接右键点击调用栈,然后选择 "转向源码" (Jump to Source),然后会直接转向内存分配相关的源码。不过,我们稍微花些时间看一下这里的可视化图形,会发现这里共享的父节点 WorldState 造成了多个泄漏问题。要验证这点,可以通过图形来过滤结果。

    过滤/导航

    和表格视图类似,图表可以通过过滤栏 (filter bar) 进行数据过滤。当启用过滤的时候,图表的数据会自动进行更新,仅显示函数符合关键词或者正则表达式的调用栈。

    有的时候调用栈会比较长,或者仅仅因为屏幕的空间不足而无法完整显示全部函数的名称。您可以使用 ctrl 加鼠标滚轮进行缩放,或者可以点击图表,使用 W、A、S、D 进行导航。

     

    验证结果

     

    增加断点,并且快速运行两次模拟器,然后发现第二次运行的时候,由于我们覆盖了第一次运行时的一个指针造成了内存泄漏。

    调试器的 Quick 视图显示第二次运行的时候 "sWorld" 已经有值了

    作为快速解决方案,我们可以在处理结束后释放掉 sWorld 变量,然后再次分析应用来验证问题是否解决。

    我们还是观察高层次的内存统计。验证了在模拟运行结束的时候删除 sWorld 释放了最初运行时占用的 70 MB。

     

    应用启动分析和采样率设置

    上面的例子展示了如何通过本地内存追踪来定位和解决内存泄漏问题。另一个本地内存追踪的常见用法是理解应用启动时内存的占用情况。在 Android Studio 4.1 中,我们还增加了在应用启动时采集本地内存使用记录的功能。您可以在 "Run/Debug Configuration" 里的 "Profiling" 标签页进行设置。

    Profiling 标签页位于 Run Configuration 对话框中

    您可以在 Run 配置对话框中自定义采集间隔或者设置应用启动时记录内存使用情况。

     

    这里您还可以为新的采集修改采样率。更小的采样率会对整个性能产生很大的影响,而更大的采样率则会遗漏一些内存分配记录。不同的采样率针对不同类型的内存问题。

     

    总结一下

    通过全新的本地内存分析器可以定位内存泄漏并且轻松洞悉内存使用情况。快去 Android Studio 4.1 试试本地内存分析器吧。如果有任何问题和反馈可以给我们留言。更多小窍门可以查阅我们今年早些时候在 Google 游戏峰会分享的内容:

    • 给我们留言

      https://issuetracker.google.com/issues/new?component=192708&template=840533

    • 腾讯视频链接

      https://v.qq.com/x/page/c0947m7dzuy.html

    • Bilibili 视频链接

      https://www.bilibili.com/video/BV18k4y1R7Fc


    推荐阅读




     点击屏末  | 使用 Memory Profiler 查看 Java 堆和内存分配


    展开全文
  • 随着不断的发展,这一架构也产生了改进,在一些场景下可能单纯使用Redis类的远程缓存已经不够了,还需要进一步配合本地缓存使用,例如Guava cache或Caffeine,从而再次提升程序的响应速度与服务性能。于是,就产生了...
  • JVM-01Java内存区域与内存溢出异常(上)【运行时区域数据】 JVM-02内存区域与内存溢出异常(中)【hotspot虚拟机对象】 JVM-03内存区域与内存溢出异常(下)【OutOfMemoryError案例】 运行时数据区总览 字节码文件被...
  • 内存和工作内存是什么?

    万次阅读 2021-06-07 22:52:15
    内存可以类比成物理硬件的主内存,但此处仅是虚拟机内存的部分 每条线程还有自己的工作内存(Working Memory)。 工作内存可以类比成处理器高速缓存 线程的工作内存中保存了被该线程使用到的变量的主内存副本拷贝...
  • 从抽象的角度来看,JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存(main memory)中,每个线程都有一个私有的本地内存(local memory),本地内存中存储了该线程以读/写共享变量的副本。...
  • 元空间与直接内存的关系

    千次阅读 2020-12-01 14:52:44
    但类的元数据信息(metadata)还在,只不过不再是存储在连续的堆空间上,而是移动到叫做“Metaspace”的本地内存(Native memory)中。 从上图可以看到,元空间和直接内存都是堆外内存,那么二者的区别是什么呢? ...
  • JVM内存分为5块,其中1--3为线程隔离,4、5为线程共享。线程隔离:1、程序计数器:分支,循环跳转、异常处理、线程恢复...3、本地方法栈:与VM stack相似,但不同的是VM stack为JVM执行java方法服务,本地方法栈为J...
  • JVM内存模型详解

    万次阅读 多人点赞 2018-02-09 14:24:27
    笔记大纲1、jvm内存结构图2、jvm按照线程共享和私有内存区域划分结构图3、堆和栈在功能、内存大小、线程共享私有进行比较4、JVM运行结构图5...本地内存8、jvm内存启动参数详解JVM内存结构图(JDK1.6)多线程共享内存区域...
  • 事实上在JVM中是用一段空间来存储程序执行期间需要用到的数据和相关信息,这段空间一般被称作为Runtime Data Area(运行时数据区),也就是我们常说的JVM内存。 一、运行时数据区域包括哪些? 根据《Ja
  • 请问 JAVA 中 元空间 和 直接内存 均是在 JVM 外开辟的高速内存区,那他们是什么关系?包含?同级?还是双方都指同一块内存
  • START SIZE RSS PSS DIRTY SWAP PERM MAPPING 0000000008048000 4K 4K 4K 0K 0K r-xp /usr/java/jre1.8.0_65/bin/java 0000000008049000 4K 4K 4K 4K 0K rw-p /usr/java/jre1.8.0_65/bin/java 000000000804a000 ...
  • fake_dynamo, 本地托管的内存内存 Amazon 模拟器 FakeDynamo 本地托管的内存内存 Amazon 模拟器 。状态不再维护这里项目。 如果你正在查找最新版本的实现,请签出 Amazon DynamoDB本地插件。版本Amazon DynamoDB API...
  •  说到内存空间,Java虚拟机把他所管理的内存分为了若干个不同的数据区域,他们各自又各自的工作。各自拥有创建与销毁的时间点,有的区域随着虚拟机进程的启动就存在了,有的区域根据用户使用线程的启动和结束而创建...
  • jdk1.8 JVM内存模型

    千次阅读 2020-03-01 00:28:00
    Hotspot虚拟机 jdk1.7 JVM内存模型是这样的 jdk1.8 做出了些改变 做出的改变有: ...绝大多数的类元数据的空间都在本地内存中分配 字符串常量池移至堆内存,其他内容包括类元信息、字段、静态...
  • JDK1.8 JVM内存划分

    万次阅读 2019-03-05 16:21:47
    不过元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制。 区域介绍 1.程序计数器  程序计数器可以看作当前线程所执行的字节...
  • 常用内存数据库介绍

    万次阅读 2018-12-29 21:33:00
    1.内存数据库简介1.概念2.内存数据库历史和发展3.常用内存数据库 1.SQLite1.SQLite最佳试用场合2.哪些场合适合使用其他的关系型数据库管理系统RDBMS2.Altibase3.Oracle 内存数据库系列 Berkeley DB 和 TimesTen1....
  • ConcurrentHashMap实现Localcache本地缓存

    千次阅读 2018-09-25 11:38:15
    除了一些像Redis等缓存外,还可以通过本地内存,作为缓存。下边将使用ConcurrentHashMap来实现本地缓存。 相关的技术: ConcurrentHashMap --数据存储,线程安全的map ScheduledExecutorService --线...
  • Java实现本地缓存

    千次阅读 2019-12-26 09:31:02
    java实现本地缓存 缓存 缓存,将程序或系统中重复用到的数据缓存在内存中,加快访问速度,减少系统开销,提高系统效率的方案。 数据存储方式主要分2种: 文件 数据保存在文件中,做持久化。 内存 数据保存在内存中...
  • java 将数据加载到内存

    万次阅读 2019-03-07 14:08:57
    将数据加载到内存中 1、建立InitListener.java package app.util; import java.util.HashMap; import java.util.Map; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener...
  • 多任务和高并发是衡量一台计算机处理器的能力重要指标之一。一般衡量一个服务器性能的...在讨论Java内存模型和线程之前,先简单介绍一下硬件的效率与一致性。 硬件的效率与一致性 由于计算机的存储设备与处理器的运算
  • JDK8中JVM堆内存划分

    万次阅读 2016-02-20 11:05:22
    说明JDK8新的堆内存划分方法,解析Matedata space作为新的内存空间跟JDK7的永久性内存相比有何不同。
  • 本地缓存介绍

    千次阅读 2018-11-22 16:46:54
    也就是将程序或系统经常要使用的对象存在内存中,以便在使用时可以快速调用,也可以避免加载数据或者创建重复的实例,以达到减少系统开销,提高系统效率的目的。 2. 为什么要用缓存 我们一般都会把数据存放在关系...
  • 有一个需求,是在servlet的业务方法中。有一些dao操作,因为表建了索引,所以做插入可能比较耗时,就想实现异步。 把dao操作的那一部分放入消息...因为不能涉及第三方工具,只能用内存实现消息队列。求大神帮忙。。。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 846,652
精华内容 338,660
关键字:

本地内存