由于线程停在某个无法进行垃圾回收的点(可能是因为已对代码进行了优化),因此无法计算表达式的值

前段时间在调试代码的过程中,调试器无法跟踪到变量的值并报异常,AnisometryT Cannot evaluate expression because a thread is stopped at a point where garbage collection is impossible, possibly because the code is optimized.

如下图所示:

发现在以上代码的下面,有一个类型的构造方法含有很多个参数:

后查找资料,发现在 .net 3.5 以及32位应用程序中,单个方法中所有参数所占用内存的总大小不能超过256个字节。

用一段简单的代码重现了以上现象:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

namespace ConsoleApplication1
{
    class TestClass
    {
        public void TestParams()
        {
            MyObject mo = new MyObject();
            Console.WriteLine(mo.ID);
            Bytes128 bytes128 = new Bytes128();            

            TestParams256(bytes128, bytes128);
        }

        private void TestParams256(Bytes128 bytes1281, Bytes128 bytes1282)
        {
            Console.WriteLine(bytes1281);
        }

        private void TestParams128(Bytes128 bytes128)
        {
            Console.WriteLine(bytes128);
        }
    }

    struct Bytes16
    {
        int word;
        int word2;
        int word3;
        int word4;
    }

    struct Bytes32
    {
        Bytes16 word16_1;
        Bytes16 word16_2;
    }

    struct Bytes64
    {
        Bytes32 word32_1;
        Bytes32 word32_2;
    }

    struct Bytes128
    {
        Bytes64 word64_1;
        Bytes64 word64_2;
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class MyObject
    {
        public int ID
        {
            get;
            set;
        }
    }
}

运行并在mo变量处断点:

其中方法TestParams256的两个参数都为Bytes128,Bytes128为Struct值类型,传递的时候会采用值传递,两个参数共占用256个字节,导致以上现象出现。

解决方法:

1、编译为x64位程序

2、采用.net 4.0 或更高版本的Framework

3、将Struct值类型定义为Class引用类型

4、将方法拆分为几个方法,确保每个方法所传递参数占用内存大小小于256个字节。

另外,以上异常只是影响调试,在程序运行过程中并不会有影响。

时间: 2024-10-07 02:20:22

由于线程停在某个无法进行垃圾回收的点(可能是因为已对代码进行了优化),因此无法计算表达式的值的相关文章

Java学习之二(线程(了解) JVM GC 垃圾回收)

线程与进程(了解)→JVM→字节码→GC 一.程序 = 算法 + 数据结构(大佬) 二.程序 = 框架 + 业务逻辑(现实) 1.线程与进程.同步与异步 1.1进程是什么? 进程就是操作系统控制的基本运行单元,说白了就是Java运行程序. 1.2什么是线程? 进程中独立运行的子任务就是一个线程 1.3什么是多线程(异步)? 多线程是多个子任务进行交替执行.例如:有A.B两个任务,A先执行,再执行B,如果是单线程执行,则需要等A先执行完之后才能够执行B:而多线程的话是A与B来回交换执行.这样可以让

Java之美[从菜鸟到高手演变]之JVM内存管理及垃圾回收

很多Java面试的时候,都会问到有关Java垃圾回收的问题,提到垃圾回收肯定要涉及到JVM内存管理机制,Java语言的执行效率一直被C.C++程序员所嘲笑,其实,事实就是这样,Java在执行效率方面确实很低,一方面,Java语言采用面向对象思想,这也决定了其必然是开发效率高,执行效率低.另一方面,Java语言对程序员做了一个美好的承诺:程序员无需去管理内存,因为JVM有垃圾回收(GC),会去自动进行垃圾回收. 其实不然: 1.垃圾回收并不会按照程序员的要求,随时进行GC. 2.垃圾回收并不会及时

.NET对象的创建、垃圾回收、非托管资源的手动处理

本篇用来梳理对象的创建.垃圾的回收,以及非托管资源的手动处理. →首先运行应用程序,创建一个Windows进程. →CLR创建一块连续的虚拟地址空间,这个地址空间就是托管堆.而且,这个地址空间最初并没有对应的物理存储空间. 虚拟地址空间分成2段.一个区段是普通堆,也叫GC堆,大小小于85000字节的引用类型对象的实例被分配在这里:另一个是大对象堆,大小大于等于85000字节的引用类型对象的实例被分配在这里. 对于客户端应用程序,每个区段的大小大致是16MB:对于服务端应用程序,每个区段的大小大致

Java 垃圾回收机制概述

摘要: Java技术体系中所提倡的 自动内存管理 最终可以归结为自动化地解决了两个问题:给对象分配内存 以及 回收分配给对象的内存,而且这两个问题针对的内存区域就是Java内存模型中的 堆区.关于对象分配内存问题,笔者的博文<JVM 内存模型概述>已经阐述了 如何划分可用空间及其涉及到的线程安全问题,本文将结合垃圾回收策略进一步给出内存分配规则.垃圾回收机制的引入可以有效的防止内存泄露.保证内存的有效使用,也大大解放了Java程序员的双手,使得他们在编写程序的时候不再需要考虑内存管理.本文着重

JVM内存管理及垃圾回收

一.JVM内存的构 Java虚拟机会将内存分为几个不同的管理区,这些区域各自有各自的用途,根据不同的特点,承担不同的任务以及在垃圾回收时运用不同的算法.总体分为下面几个部分: 程序计数器(Program Counter Register).JVM虚拟机栈(JVM Stacks).本地方法栈(Native Method Stacks).堆(Heap).方法区(Method Area) 如下图: 1.程序计数器(Program Counter Register) 这 是一块比较小的内存,不在Ram上

.net 4.0 中的特性总结(三):垃圾回收

1.内存基础知识 每个进程都有其自己单独的虚拟地址空间. 同一台计算机上的所有进程共享相同的物理内存,如果有页文件,则也共享页文件. 默认情况下,32 位计算机上的每个进程都具有 2 GB 的用户模式虚拟地址空间. 作为一名应用程序开发人员,您只能使用虚拟地址空间,请勿直接操控物理内存. 垃圾回收器为您分配和释放托管堆上的虚拟内存. 如果您编写的是本机代码,请使用 Win32 函数处理虚拟地址空间. 这些函数为您分配和释放本机堆上的虚拟内存. 虚拟内存有三种状态: 可用. 该内存块没有引用关系,

JVM基础(5)-垃圾回收机制

一.对象引用的类型 Java 中的垃圾回收一般是在 Java 堆中进行,因为堆中几乎存放了 Java 中所有的对象实例.谈到 Java 堆中的垃圾回收,自然要谈到引用.在 JDK1.2 之前,Java 中的引用定义很很纯粹:如果 reference 类型的数据中存储的数值代表的是另外一块内存的起始地址,就称这块内存代表着一个引用.但在 JDK1.2 之后,Java 对引用的概念进行了扩充,将其分为强引用(Strong Reference).软引用(Soft Reference).弱引用(Weak

java垃圾回收算法

(1)引用计数法 这是最经典和最古老的一种,它的工作原理是为每个对象配备一个计数器,只有这个对象被引用了,引用计数器就加1,当引用失效时,计数器减一,只要计数器为0,意味着不再被使用,于是该对象就可以被回收了. 优点:实现简单: 缺点:无法处理循环引用情况.即有应该被回收的垃圾对象A.B,他们互相引用,除此之外无其他引用,然而他们计数器值不是0,因此无法回收,从而造成内存泄漏. (2)标记-清除算法 这个算法将垃圾回收分为两个阶段,标记阶段和清除阶段,在标记阶段,首先通过根结点,标记所有从根结点

JAVA当中内存管理与垃圾回收!

很多Java面试的时候,都会问到有关Java垃圾回收的问题,提到垃圾回收肯定要涉及到JVM内存管理机制,Java语言的执行效率一直被C.C++程序员所嘲笑,其实,事实就是这样,Java在执行效率方面确实很低,一方面,Java语言采用面向对象思想,这也决定了其必然是开发效率高,执行效率低.另一方面,Java语言对程序员做了一个美好的承诺:程序员无需去管理内存,因为JVM有垃圾回收(GC),会去自动进行垃圾回收. 其实不然: 1.垃圾回收并不会按照程序员的要求,随时进行GC. 2.垃圾回收并不会及时