天道酬勤,学无止境

.NET Garbage Collection - What does it affect?

We have a situation where we are considering forcing a garbage collection on a server that is very low on RAM (3.6/4GB used on average). No, it's not really an option to upgrade this server unfortunately.

One of our service processes (written indirectly in C++ (don't ask...)) does work with the .NET components and then sleeps for 10 minutes. When that service is sleeping, it is often hanging on to 600MB of RAM that could be shared with other processes. Seems somehow related to WSE tracing being turned on for debugging. I can watch it wake up and GC on the next iteration on the first COM call to .NET - however then the process does some work and by the time it goes to sleep the RAM use is back up around 600MB... well, you can see where this goes...

The Question: I'm considering adding a garbage collection just before the process goes to sleep. There are other services on this box that are doing .NET related tasks. When I call a garbage collection in this service process, does that GC affect all other .NET related processes on the box or just the process that requests the collection? I'm a bit worried about creating some sort of performance problem for processes outside of the one I care about.

评论

It just affects the process it's called in (but will affect all Application Domains in the process). However, be warned that this will not release the memory to the OS. If you want to release the memory to the OS, a way to do it is:

private static void minimizeMemory()
{
    GC.Collect(GC.MaxGeneration);
    GC.WaitForPendingFinalizers();
    SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle,
        (UIntPtr) 0xFFFFFFFF, (UIntPtr) 0xFFFFFFFF);
}

[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SetProcessWorkingSetSize(IntPtr process,
    UIntPtr minimumWorkingSetSize, UIntPtr maximumWorkingSetSize);

The big caveat here is why. Unless you're noticing that memory is thrashing or swapping is a performance bottleneck (or you're writing an end-user app), there's no real reason to be concerned about memory usage. Forcing a GC can be slow. Reducing the heap will cause the heap to need to be re-allocated from VM. In addition, the .NET GC is reactive, using program behavior to increase its efficiency. By forcing a collection, you don't allow the GC to tune itself to your program's behavior, further reducing performance.

I know this from experience -- I asked this question a while back and even came up with a timer-based class to call the method above after leaving a high-memory operation (run every 5 minutes). Following this, the process working set would reduce itself a lot -- by swapping it to disk. Over the next couple seconds, it would read back the most frequently used parts, a couple minutes later (when the task was run again), it would again do a bunch of allocation. Timing (not even profiling) the process showed that with the collection, there was about a 0.2s (!) slowdown during the allocation of VM from the OS for the task.

You would be wise to get a profiler out and look at why objects are not being garbage collected efficiently. It may be they're ending up in gen2 unecessarily and you could refactor it to allow it to get rid of objects more quickly.

You could also try ensuring the .NET part runs with the server version of the garbage collector, the default is the workstation version and this prefers to keep the process active rather than running the GC (i.e it's tuned to keep a UI responsive). The server version is more aggressive and runs parallel GCs, one-per core as well.

Add the following to the app.config:

<Configuration>
    <runtime>
        <gcServer enabled=“true“ />
    </runtime>
</Configuration> 

Linky to more information

Aside from additional CPU utilization for the duration of the collection, forcing a garbage collection does not result in an impact to other .NET processes. However, forcing a garbage collection will not - in most cases - result in a release of physical memory.

The mapping of physical memory to the address space of a process is a complicated thing. A garbage collection in a .NET process may increase the free space in the managed heap - but it isn't guaranteed to result in a decrease in the working set size (the memory your Win32 process is given from the OS). Even if you could get such a scheme working - it would be fragile at best, and may not work under all circumstances.

There is a Win32 method called SetProcessWorkingSetSize() which allows you to control the minimum and maximum physical memory allocated to a process. You may want to look into this in conjunction with the forced collection scheme you are exploring.

Along with the other answers referring directly to your use of GC.Collect, I would suggest you not only do some simple profiling, but also do a code review and ensure that you are properly releasing resources when you are done using them.

Do you call Dispose on all objects that implement IDisposable when you are done using them? If you have classes which contain private variables that implement IDisposable, does the containing class implement IDisposable and do you call Dispose?

Are there places where you can use a using statement to ensure Dispose gets called? None of these things will help with physical memory, but it will help with things like HANDLE's to windows objects, etc.

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • 按参考和.net垃圾收集的C#参数(C# parameters by reference and .net garbage collection)
    问题 我一直在尝试弄清.NET垃圾收集系统的复杂性,并且我有一个与C#参考参数有关的问题。 如果我理解正确,则方法中定义的变量将存储在堆栈中,并且不受垃圾回收的影响。 因此,在此示例中: public class Test { public Test() { } public int DoIt() { int t = 7; Increment(ref t); return t; } private int Increment(ref int p) { p++; } } DoIt()的返回值将为8。由于t在堆栈上,因此该内存无法进行垃圾回收或压缩,并且Increment()中的引用变量将始终指向t的正确内容。 但是,假设我们有: public class Test { private int t = 7; public Test() { } public int DoIt() { Increment(ref t); return t; } private int Increment(ref int p) { p++; } } 现在,t存储在堆中,因为它是类的特定实例的值。 如果将此值作为参考参数传递,这可能不是问题吗? 如果我将t用作参考参数,则p将指向t的当前位置。 但是,如果垃圾收集器在压缩期间移动了该对象,这会不会弄乱Increment()中对t的引用?
  • ES6 const 会影响垃圾回收吗?(Does ES6 const affect garbage collection?)
    问题 在 Kyle Simpson 的新书《你不知道 JS:ES6 及更高版本》中,我找到了以下片段: 警告将对象或数组分配为常量意味着在该常量的词法范围消失之前,该值将无法被垃圾收集,因为永远不能取消设置对该值的引用。 这可能是可取的,但如果这不是您的意图,请小心! (摘自:Simpson, Kyle。“你不知道 JS:ES6 及以后。”O'Reilly Media, Inc.,2015-06-02。iBooks。此材料可能受版权保护。) 据我所知,他没有对此进行扩展,在 Google 上 10 分钟什么也没有发现。 这是真的吗,如果是这样,“永远不能取消对值的引用”究竟是什么意思? 我已经习惯于将不会更改的变量声明为const ,这在实际的具体性能/内存方面是一个坏习惯吗? 回答1 警告将对象或数组分配为常量意味着在该常量的词法范围消失之前,该值将无法被垃圾收集,因为永远不能取消设置对该值的引用。 这可能是可取的,但如果这不是您的意图,请小心! 该注释听起来有点像警告而不是必要的(甚至可能有点愚蠢),并试图从这种情况中找出某种特殊情况。 使用const变量声明,您不能将类似于""或null的内容分配给变量以清除其内容。 这确实是内存管理方面的唯一区别。 自动垃圾回收完全不受其是否声明为const 。 因此,如果您希望将来能够出于任何原因更改变量的内容
  • Does ES6 const affect garbage collection?
    In Kyle Simpson's new title, You don't know JS: ES6 and beyond, I find the following snippet: WARNING Assigning an object or array as a constant means that value will not be able to be garbage collected until that constant’s lexical scope goes away, as the reference to the value can never be unset. That may be desirable, but be careful if it’s not your intent! (Excerpt From: Simpson, Kyle. “You Don’t Know JS: ES6 & Beyond.” O'Reilly Media, Inc., 2015-06-02. iBooks. This material may be protected by copyright.) As far as I can see, he doesn't expand on this, and 10 minutes on Google turns up
  • 2021年初Java核心面试总结:Java+Redis+数据库+解决方案+分布式
    2021年已经到了复工期,给准备跳槽的大家整理了今年来最经典的面试真题100道,每个题目都有详细的解答,收集了java基础、RabbitMQ,微服务、MySQL数据库、Java并发、JVM,Redis、设计模式,Spring / Spring MVC,等专题的经典面试真题,和详细分析。 数据库篇 事务四大特性(ACID)原子性、一致性、隔离性、持久性?事务的并发?事务隔离级别,每个级别会引发什么问题,MySQL默认是哪个级别?MySQL常见的三种存储引擎(InnoDB、MyISAM、MEMORY)的区别?MySQL的MyISAM与InnoDB两种存储引擎在,事务、锁级别,各自的适用场景?MySQL B+Tree 索引和 Hash 索引的区别?sql 查询语句确定创建哪种类型的索引,如何优化查询有哪些锁(乐观锁悲观锁),select 时怎么加排它锁?数据库的读写分离、主从复制,主从复制分析的 7 个问题?MySQL 都有什么锁,死锁判定原理和具体场景,死锁怎么解决?MySQL 高并发环境解决方案? 这些问题都是抽取了部分发出来,答案解析和知识点都整理在这个近500页的Java学习笔记文档里了,详细内容有很多,为了不影响阅读,可看整理的《Java架构进阶笔记》,点这里即可获取 Spring篇 Spring IoC、AOP 原理Spring Bean 生命周期Spring Bean
  • 阿里资深技术官详解「性能优化」:JVM调优+Tomcat调优+MySQL调优
    前言 性能优化是什么? 答:性能优化,简而言之,就是在不影响系统运行正确性的前提下,使之运行地更快,完成特定功能所需的时间更短。 前提是什么? 答:不影响系统运行正确性 目的是什么? 答:运行地更快时间更短,( 改善应用的“吞吐量”和“延迟”。) 在JAVA程序中,性能问题的大部分原因并不在于JAVA语言,而是程序本身。养成良好的编码习惯非常重要,能够显著地提升程序性能。今天就由阿里资深技术官来详解「性能优化」问题,从JVM、Tomcat、MySQL三种调优方式来详细讲解,以下含一些面试题、脑图以及调优文档等资料,需要电子版的可以直接(点击我)免费领取。 JVM 调优篇 01 JVM相关面试题 什么是JVM?JVM由哪些部分组成?类加载器是有了解吗?类加载器是如何加载 class 文件的?双亲委派模型(Parent Delegation Model)?内存模型以及分区,需要详细到每个区放什么。类似-Xms、-Xmn这些参数的含义简述一下 Java 中创建一个对象的过程?如何判断一个对象是否已经死去?垃圾回收算法有哪些?GC什么时候开始?JVM 内存分哪几个区,每个区的作用是什么?GC 的三种收集方法:标记清除、标记整理、复制算法的原理与特点,分别用在什么地方,如果让你优化收集方法,有什么思路?… 02 JVM和性能优化脑图(X-mind)
  • 垃圾收集是否发生在流程级别或应用程序域级别?(Does garbage collection happen at the process level or appdomain level?)
    问题 FullGC通常会在运行时暂停所有线程。 有两个AppDomain,每个AppDomain运行多个线程。 当GC运行时,所有线程都将暂停,还是仅其中一个AppDomain线程暂停? 回答1 很难回答,最好的办法就是测试一下: using System; using System.Reflection; public class Program : MarshalByRefObject { static void Main(string[] args) { var dummy1 = new object(); var dom = AppDomain.CreateDomain("test"); var obj = (Program)dom.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, typeof(Program).FullName); obj.Test(); Console.WriteLine("Primary appdomain, collection count = {0}, gen = {1}", GC.CollectionCount(0), GC.GetGeneration(dummy1)); Console.ReadKey(); } public void Test() { var
  • Java面试解析总结:Java+Redis+数据库+算法与数据结构+分布式
    金九银十即将到来,给大家整理了今年来最经典的面试真题1000+道,每个题目都有详细的解答,收集了java基础、RabbitMQ,微服务、MySQL数据库、Java并发、JVM,Redis、设计模式,Spring / Spring MVC,等专题的经典面试真题,和详细分析。 数据库篇 事务四大特性(ACID)原子性、一致性、隔离性、持久性?事务的并发?事务隔离级别,每个级别会引发什么问题,MySQL默认是哪个级别?MySQL常见的三种存储引擎(InnoDB、MyISAM、MEMORY)的区别?MySQL的MyISAM与InnoDB两种存储引擎在,事务、锁级别,各自的适用场景?MySQL B+Tree 索引和 Hash 索引的区别?sql 查询语句确定创建哪种类型的索引,如何优化查询有哪些锁(乐观锁悲观锁),select 时怎么加排它锁?数据库的读写分离、主从复制,主从复制分析的 7 个问题?MySQL 都有什么锁,死锁判定原理和具体场景,死锁怎么解决?MySQL 高并发环境解决方案? **这些问题都是抽取了部分发出来,答案解析和知识点都整理在这个近500页的Java学习笔记文档里了,详细内容有很多,为了不影响阅读,可看整理的《Java架构进阶笔记》,见后文 Spring篇 Spring IoC、AOP 原理Spring Bean 生命周期Spring Bean
  • 面试问题:符合垃圾收集条件的对象(Interview question: Objects eligible for garbage collection)
    问题 输入以下代码: class A { Boolean b; A easyMethod(A a){ a = null; return a; } public static void main(String [] args){ A a1 = new A(); A a2 = new A(); A a3 = new A(); a3 = a1.easyMethod(a2); a1 = null; // Some other code } } 问题是,在// Some other code之前, // Some other code多少个对象符合垃圾回收的条件。 那么正确的答案是(至少那是面试官的答案): 2-布尔值b因为它是包装器,而a1 。 你能请我解释一下为什么不对a2和a3进行垃圾回收吗? 稍后编辑: 好吧,我想我现在明白了。 起初有点令人困惑,但现在我确信面试官是错的。 我最初的错误是,起初我不认为Java仅通过值传递,因此不可能从以“ a2”为参数的函数内部使a2为null,因为a2实际上是a2的副本。 布尔值b的部分确实非常明显。 感谢您的答复,之后,我将发送一些面试反馈:)。 回答1 假设go被认为是easyMethod它的工作原理如下 class A { Boolean b; A easyMethod(A a){ a = null; // the reference to
  • 2021年金三银四Java面试解析总结:Java+Redis+数据库+解决方案+分布式..
    2021年金三银四已经结束了,给大家整理了今年来最经典的面试真题100道,每个题目都有详细的解答,收集了java基础、RabbitMQ,微服务、MySQL数据库、Java并发、JVM,Redis、设计模式,Spring / Spring MVC,等专题的经典面试真题,和详细分析。 数据库篇 事务四大特性(ACID)原子性、一致性、隔离性、持久性? 事务的并发?事务隔离级别,每个级别会引发什么问题,MySQL默认是哪个级别? MySQL常见的三种存储引擎(InnoDB、MyISAM、MEMORY)的区别? MySQL的MyISAM与InnoDB两种存储引擎在,事务、锁级别,各自的适用场景? MySQL B+Tree 索引和 Hash 索引的区别? sql 查询语句确定创建哪种类型的索引,如何优化查询 有哪些锁(乐观锁悲观锁),select 时怎么加排它锁? 数据库的读写分离、主从复制,主从复制分析的 7 个问题? MySQL 都有什么锁,死锁判定原理和具体场景,死锁怎么解决? MySQL 高并发环境解决方案? 这些问题都是抽取了部分发出来,答案解析和知识点都整理在这个近500页的Java学习笔记文档里了,详细内容有很多,为了不影响阅读,可看整理的《Java架构进阶笔记》,文末有获取方式 Spring篇 Spring IoC、AOP 原理 Spring Bean 生命周期 Spring
  • 默认堆栈大小是多少,它可以增长吗,它如何与垃圾回收一起工作?(What is the default stack size, can it grow, how does it work with garbage collection?)
    问题 我知道每个线程都有自己的stack 。 基本类型和引用保留在堆栈上,并且没有对象保留在堆栈上。 我的问题是: 堆栈可以增长多少? (如参数Xms和Xmx ) 我们可以限制它的增长吗? 堆栈是否具有默认的最小值和最大值? 垃圾收集如何在堆栈上工作? 回答1 堆栈可以增长多少? 您可以使用名为ss的VM选项来调整最大堆栈大小。 VM选项通常使用-X {option}传递。 因此,您可以使用java -Xss1M将最大堆栈大小设置为1M。 每个线程至少有一个堆栈。 某些Java虚拟机(JVM)将Java堆栈(Java方法调用)和本机堆栈(VM中的本机方法调用)放入一个堆栈中,并使用称为“托管到本机框架”(称为M2nFrame)执行堆栈退卷。 一些JVM分别保留两个堆栈。 在大多数情况下, Xss设置Java堆栈的大小。 对于许多JVM,它们在不同平台上为堆栈大小放置了不同的默认值。 我们可以限制这种增长吗? 发生方法调用时,将在该线程的堆栈上创建一个新的堆栈框架。 堆栈将包含局部变量,参数,返回地址等。在Java中,您永远不能将对象放在堆栈上,只能将对象引用存储在堆栈上。 由于数组也是Java中的对象,因此数组也不存储在堆栈中。 因此,如果通过将局部基本变量,参数分组为对象来减少它们的数量,则可以减少堆栈上的空间。 实际上
  • Java主要和次要垃圾回收(Java Major and Minor Garbage Collections)
    问题 我一直在阅读Java和SO Q&A中的Garbage Collection,但是对于Garbage Collection的类型感到困惑。 让我们以吞吐量收集器为例。 (又名并行收集器)。 文档说它使用多个线程来进行次要集合,而使用单个线程来进行主要集合(与串行收集器相同)。 现在我的问题是: 完整GC的含义是什么:a)是否意味着次要收藏和主要收藏都已完成? 或b)完整GC ==主要收藏? 哪一个? 如果是a),是否表示次要集合仍使用多个线程完成,而次要集合则使用单个线程完成? 如果是b),是否意味着年轻一代和老一代都使用单线程清除了? 另外,4. Full GC是否也只影响OldGeneration或YoungGeneration? 提前致谢。 回答1 让我解释。 让我们以吞吐量收集器为例。 (又名并行收集器)。 文档说它使用多个线程来进行次要集合,而使用单个线程来进行主要集合(与串行收集器相同)。 这是要理解的东西。 默认情况下,在大多数较新的系统上,JVM使用两个不同的年轻代和老一代垃圾收集器。 在我的机器上:我有年轻一代的并行新收集器和老一代并行的Mark and Sweep收集器。 当JVM无法为新对象分配空间时会触发次要集合(请记住:新对象始终在Young Generation的Eden区域中分配)。 下一个问题: 完整GC的含义是什么:a
  • 什么时候该对象有资格进行垃圾收集?(When Is The Object Eligible For Garbage Collection?)
    问题 在下面的代码,因为amethod被调用。 最初由myObject引用的对象在什么时间点/行有资格进行垃圾回收? class Test { private Object classObject; public void amethod() { Object myObject = new Object(); classObject = myObject; myObject = null; } } 并且,如果classObject或amethod的访问修饰符为public,protected,default或static,那么会影响对象在什么时候可以进行垃圾回收? 如果是这样,它将如何受到影响? 我首先想到的是,当测试对象符合垃圾收集条件时,该对象符合垃圾收集条件。 但话又说回来。 优化器可能知道永远不会从中读取classObject,在这种情况下, classObject = myObject; 将被优化,并且myObject = null; 才有资格进行垃圾收集。 回答1 该对象将不会成为垃圾回收的候选对象,直到对该对象的所有引用都被丢弃。 Java对象是通过引用分配的,因此当您拥有 classObject = myObject; 您为堆上的同一对象分配了另一个引用。 所以这条线 myObject = null; 仅摆脱一种参考。 要使myObject成为垃圾收集的候选者
  • Java高频面试解析:Java+Redis+数据库+算法与数据结构+分布式
    金九银十,给大家整理了今年来最经典的面试真题1000+道,每个题目都有详细的解答,收集了java基础、RabbitMQ,微服务、MySQL数据库、Java并发、JVM,Redis、设计模式,Spring / Spring MVC,等专题的经典面试真题,和详细分析。 数据库篇 事务四大特性(ACID)原子性、一致性、隔离性、持久性?事务的并发?事务隔离级别,每个级别会引发什么问题,MySQL默认是哪个级别?MySQL常见的三种存储引擎(InnoDB、MyISAM、MEMORY)的区别?MySQL的MyISAM与InnoDB两种存储引擎在,事务、锁级别,各自的适用场景?MySQL B+Tree 索引和 Hash 索引的区别?sql 查询语句确定创建哪种类型的索引,如何优化查询有哪些锁(乐观锁悲观锁),select 时怎么加排它锁?数据库的读写分离、主从复制,主从复制分析的 7 个问题?MySQL 都有什么锁,死锁判定原理和具体场景,死锁怎么解决?MySQL 高并发环境解决方案? 这些问题都是抽取了部分发出来,答案解析和知识点都整理在这个近500页的Java学习笔记文档里了,详细内容有很多,为了不影响阅读,可看整理的《Java架构进阶笔记》,关注文末公众号获取 Java面试解析总结:Java+Redis+数据库+解决方案+分布式.. Spring篇 Spring IoC、AOP
  • 2020年末Java面试解析总结:Java+Redis+数据库+解决方案+分布式..
    2020结束了,给大家整理了最经典的面试真题100道,每个题目都有详细的解答,收集了java基础、RabbitMQ,微服务、MySQL数据库、Java并发、JVM,Redis、设计模式,Spring / Spring MVC,等专题的经典面试真题,和详细分析。 数据库篇 事务四大特性(ACID)原子性、一致性、隔离性、持久性?事务的并发?事务隔离级别,每个级别会引发什么问题,MySQL默认是哪个级别?MySQL常见的三种存储引擎(InnoDB、MyISAM、MEMORY)的区别?MySQL的MyISAM与InnoDB两种存储引擎在,事务、锁级别,各自的适用场景?MySQL B+Tree 索引和 Hash 索引的区别?sql 查询语句确定创建哪种类型的索引,如何优化查询有哪些锁(乐观锁悲观锁),select 时怎么加排它锁?数据库的读写分离、主从复制,主从复制分析的 7 个问题?MySQL 都有什么锁,死锁判定原理和具体场景,死锁怎么解决?MySQL 高并发环境解决方案? 这些问题都是抽取了部分发出来,答案解析和知识点都整理在这个近500页的Java学习笔记文档里了,详细内容有很多,为了不影响阅读,可看整理的《Java架构进阶笔记》,有需要的朋友,点此免费获取! Spring篇 Spring IoC、AOP 原理Spring Bean 生命周期Spring Bean
  • JVM垃圾回收机制
    文章引用:https://blog.csdn.net/antony9118/article/details/51375662 https://blog.csdn.net/antony9118/article/details/51425581 一、背景介绍 与C/C++相比,JAVA并不要求我们去人为编写代码进行内存回收和垃圾清理。JAVA提供了垃圾回收器(garbage collector)来自动检测对象的作用域),可自动把不再被使用的存储空间释放掉,也就是说,GC机制可以有效地防止内存泄露以及内存溢出。 1.JAVA 垃圾回收器的主要任务是: 分配内存 确保被引用对象的内存不被错误地回收 回收不再被引用的对象的内存空间 凡事都有两面性。垃圾回收器在把程序员从释放内存的复杂工作中解放出来的同时,为了实现垃圾回收,garbage collector必须跟踪内存的使用情况,释放没用的对象,在完成内存的释放之后还需要处理堆中的碎片, 这样做必定会增加JVM的负担。 2.为什么要了解JAVA的GC机制? 综上所述,除了作为一个程序员,精益求精是基本要求之外,深入了解GC机制让我们的代码更有效率,尤其是在构建大型程序时,GC直接影响着内存优化和运行速度。 . 二、JVM内存结构 了解JVM的垃圾回收机制,要先了解JVM内存结构。 其中栈内存可以再细分为java虚拟机栈和本地方法栈
  • JVM--怎么选择一款合适的垃圾收集器
    JVM–怎么选择一款合适的垃圾收集器 echo编辑整理。欢迎添加echo微信(微信号:t2421499075)交流学习。该文章不支持转载,主要内容来自读书笔记和网络博客,以及视频学习整理。 参考资料列表: jdk不同版本的垃圾收集器:https://blog.csdn.net/weixin_34166847/article/details/94133616 鼓泡学院资料集 《深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)》 --周志明 衡量垃圾收集器的三项最重要的指标是:内存占用(Footprint)、吞吐量(Throughput)和延迟(Latency),但是我们仅仅知道这些,再去了解一下诸多的垃圾收集器,并不能有效合理的选择一款适合我们的垃圾收集器。在网上看到很多的文章描述,都是请根据每一个垃圾收集器的特性和对应的场景来使用。这一句话其实一点也没错,但是对于一个接触垃圾收集器不多的人来说,可能就会造成一脸懵。本文主要整理选择垃圾收集器的方法 越先进的垃圾收集器越好吗? 答案是否定的。在我们JDK不断更新的过程过,我们发现很多的垃圾收集器都是根据JDK的版本来调整的,比如G1就是JDK11的环境发布的,ZGC应该是JDK13的环境发布的。很显然,目前市场上很多公司还在使用JDK1.7、JDK1.8,使用JDK11的都很少,所以有可能牛头不对马嘴 垃圾收集器选择场景分析
  • GC机制,你真的了解吗?
    前言 GC(Garbage Collection)相信是每一个程序猿(媛)都熟知的了。作为一个Android开发者,无疑我们是幸福的,因为我们不用像C语言那样还需要手动进行垃圾回收,但同时我们又是不幸的,由于android市场的碎片化,各个型号的手机迥然不同,适配起来相当麻烦,其中最需要避免的就是Out Of Memory了。那么深入的了解GC机制就是每一个android开发者的必修课。 JVM运行时的内存分配机制 JVM的内存分配可以通过上图来说明,程序运行时会将所申请的内存分为五大块,而不仅仅是我们通常所说的堆内存和栈内存。它们分别是一个程序计数器、一个方法区、一个堆内存和两个栈内存(虚拟机栈和本地方法栈)。 程序计数器:可能比较陌生,但它的概念和用途却是很好理解的,程序计数器是线程私有的,生命周期随线程的创建而创建,随线程消亡而消亡。主要用于记录当前线程执行的位置。通常我们所用的线程切换、循环、跳转等都需要依赖这个计数器来完成。 方法区:主要用于存储已经被JVM加载的常量、静态变量等,它是能够被线程共享的。 本地方法栈:主要针对的是native方法,因此一般在JNI开发、NDK开发涉及较多。它是线程私有的。 虚拟机栈:也是线程私有的,JVM是基于栈的解释器执行的。每个方法被执行的时候,JVM都会在虚拟机中创建一个栈帧(Stack Frame)。而每一个栈帧内又包含了局部变量表
  • Java内存以及垃圾回收常见面试题目
    Java内存以及垃圾回收常见面试题目 内存方面JVM 三大性能调优参数Java的堆和栈的区别 垃圾回收方面:GC相关Object 的finalize() 方法的作用是否和C++的析构函数作用相同Java中的强引用,软引用,弱引用,虚引用有什么作用 内存方面 JVM 三大性能调优参数 Xss : 规定了每个线程虚拟机栈(堆栈)的大小Xms: 堆的初始大小Xmx: 堆的最大大小 光看这三个参数可能没什么概念,配合这张图, 说的就是下图中紫色部分, 如下的指令 java -Xms128m -Xmx128m -Xss256k -jar xxx.jar 这也就解释了每个线程虚拟机栈的Xss为什么是k级别的,这个参数会影响线程并发数量的大小;Xms是堆的初始大小,如果申请的线程超过了这个堆栈的初始大小,就会进行扩容,扩容到Xmx 就不能再扩容,如果再申请,就会抛出异常。 扩容这个过程,会导致内存抖动,影响程序运行的稳定性。 Java的堆和栈的区别 静态存储 : 编译时确定每个数据目标在运行时的存储空间需求,不能有变量循环递归栈式存储: 数据区需求在编译时未知,运行时模块入口前确定,由于是栈——按照先进后出的原则存储堆式储存: 编译时货运行时模块入口都无法确定,动态分配,比如长度可变串和对象实例。分配原则——随意分配。 堆和栈之间的联系:引用对象,数组时,栈里定义变量保存堆中目标的首地址。
  • JVM——GC垃圾回收机制的八个重要面试问题你知道了吗?
    GC垃圾回收机制 GC是干什么的为什么要有GC为什么C/C++中不引入GCGC要回收哪些内存回收的基本单位回收对象的基本思路引用计数法有一个致命缺陷:无法解决循环引用的问题 分代回收 GC是干什么的 C语言特点,相当于是一个手动挡的汽车,挂挡比较麻烦,但是能做到更精确的控制 Java语言,相当于是一个自动挡的汽车,开起来更方便,不能像手动车那样精准控制、 内存管理: C语言中的内存,申请之后,需要手动释放(free/delete)一旦忘记释放,就容易导致“内存泄漏” Java中的内存,申请之后,不需要手动释放(GC) 没有垃圾回收,需要程序主动归还内存(取决于用户的素质),有了垃圾回收,相当于有了一个专门负责的人 为什么要有GC 内存申请的时机很好确定,但是释放时机是不好确定的。 比如从一个地方借到一个桌子,你可能要用来举办活动、上课。。。等等,你不确定最后那个桌子是否还需要用,就容易忘记还要还桌子。有一个GC就是相当于有一个人专门管理回收。 为什么C/C++中不引入GC 引入GC会有额外代价 1、需要消耗的资源 2、GC回收内存没有手动释放更及时,用完立刻手动释放,GC还要兼顾到其他资源。 3、GC会影响到正常的程序工作(影响到程序的执行效率STW(Stop the world)问题) GC要回收哪些内存 堆 主要回收 方法区(类对象) GC需要回收方法区的内存,但是方法区空间小
  • Does the StackMapTable affect the garbage collection behavior?
    I have code like this: public class TestGC { private static final int _10MB = 10 * 1024 * 1024; // 10MB public static void main(String[] args) { test1(); // test2(); } public static void test1() { int i = 1; if (i > 0) { byte[] data = new byte[_10MB]; } System.gc(); } public static void test2() { if (true) { byte[] data = new byte[_10MB]; } System.gc(); } } I run it with jvm option -verbose:gc, My java env: java version "1.7.0_79" Java(TM) SE Runtime Environment (build 1.7.0_79-b15) Java HotSpot(TM) 64-Bit Server VM (build 24.79-b02, mixed mode) CASE-1: Run with method test1() invoked, console