- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试在我正在编写的程序中实现多线程以实现某些任务并行性。该程序利用Spring框架并在Pivotal Cloud Foundry上运行。它偶尔会崩溃,所以我进去查看日志和性能指标;这是我发现它有内存泄漏的时候。经过一些测试后,我将罪魁祸首的范围缩小到了我的线程实现。我对JVM中GC的理解是,它不会处置未死的线程,也不会处置任何仍在被另一个对象或后面的可执行代码行引用的对象。然而,我根本没有保留对该线程的任何引用,如果我这样做,它声称一旦完成运行就会将自己置于死亡状态,所以我不知道是什么导致了泄漏。
我已经编写了一个干净的 PoC 来演示泄漏。它使用一个休息 Controller ,这样我就可以控制线程的数量,一个可运行的类,因为我的真实程序需要参数,以及一个字符串来占用内存中的任意空间,该空间将由真实程序中的其他字段保存(使泄漏更多)明显)。
package com.example;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class LeakController {
@RequestMapping("/Run")
public String DoWork(@RequestParam("Amount") int amount, @RequestParam("Args") String args)
{
for(int i = 0; i < amount; i++)
new Thread(new MyRunnable(args)).start();
return "Workin' on it";
}
public class MyRunnable implements Runnable{
String args;
public MyRunnable(String args){ this.args = args; }
public void run()
{
int timeToSleep = Integer.valueOf(args);
String spaceWaster = "";
for (int i = 0; i < 10000; i ++)
spaceWaster += "W";
System.out.println(spaceWaster);
try {Thread.sleep(timeToSleep);} catch (InterruptedException e) {e.printStackTrace();}
System.out.println("Done");
}
}
}
谁能解释一下为什么这个程序会泄漏内存?
编辑:我收到了一些关于字符串分配与字符串构建和字符串池的回复,因此我将代码更改为以下内容
int[] spaceWaster = new int[10000];
for (int i = 0; i < 10000; i ++)
spaceWaster[i] = 512;
System.out.println(spaceWaster[1]);
它仍然泄漏。
编辑:在获取一些实数来响应 Voo 时,我注意到一些有趣的事情。调用新线程开始消耗内存,但仅限于一定程度。在永久增长约 60mb 后,新的基于整数的程序将停止进一步增长,无论它如何插入。这和spring框架分配内存的方式有关系吗?
我还认为回到 String 示例是有好处的,因为它与我的实际用例更密切相关;这是对传入的 JSON 进行正则表达式操作,每秒数百个这样的 JSON。考虑到这一点,我将代码更改为:
@RestController
public class LeakController {
public static String characters[] = {
"1","2","3","4","5","6","7","8","9","0",
"A","B","C","D","E","F","G","H","I","J","K","L","M",
"N","O","P","Q","R","S","T","U","V","W","X","Y","Z"};
public Random rng = new Random();
@RequestMapping("/Run")
public String GenerateAndSend(@RequestParam("Amount") int amount)
{
for(int i = 0; i < amount; i++)
{
StringBuilder sb = new StringBuilder(100);
for(int j = 0; j< 100; j++)
sb.append(characters[rng.nextInt(36)]);
new Thread(new MyRunnable(sb.toString())).start();
System.out.println("Thread " + i + " created");
}
System.out.println("Done making threads");
return "Workin' on it";
}
public class MyRunnable implements Runnable{
String args;
public MyRunnable(String args){ this.args = args; }
public void run()
{
System.out.println(args);
args = args.replaceAll("\\d+", "\\[Number was here\\]");
System.out.println(args);
}
}
}
这个新应用程序表现出与整数示例类似的行为,它永久增长约 50mb(在 2000 个线程之后),并从那里逐渐减少,直到我无法注意到每批新的 1000 个线程有任何内存增长(比原始线程增长约 85mb)部署内存)。
如果我更改它以删除 stringbuilder:
String temp = "";
for(int j = 0; j< 100; j++)
temp += characters[rng.nextInt(36)];
new Thread(new MyRunnable(temp)).start();
它会无限期地泄漏;我假设一旦生成了所有 36^100 个字符串,它就会停止。
结合这些发现,我想我真正的问题可能是字符串池的问题和 spring 如何分配内存的问题。我仍然无法理解的是,在我的实际应用程序中,如果我创建一个可运行对象并在主线程上调用 run() ,内存似乎不会激增,但如果我创建一个新线程并为其提供可运行对象,那么内存就会跳转。这是我正在构建的应用程序中当前可运行的样子:
public class MyRunnable implements Runnable{
String json;
public MyRunnable(String json){
this.json = new String(json);
}
public void run()
{
DocumentClient documentClient = new DocumentClient (END_POINT,
MASTER_KEY, ConnectionPolicy.GetDefault(),
ConsistencyLevel.Session);
System.out.println("JSON : " + json);
Document myDocument = new Document(json);
System.out.println(new DateTime().toString(DateTimeFormat.forPattern("MM-dd-yyyy>HH:mm:ss.SSS"))+">"+"Created JSON Document Locally");
// Create a new document
try {
//collectioncache is a variable in the parent restcontroller class that this class is declared inside of
System.out.println("CollectionExists:" + collectionCache != null);
System.out.println("CollectionLink:" + collectionCache.getSelfLink());
System.out.println(new DateTime().toString(DateTimeFormat.forPattern("MM-dd-yyyy>HH:mm:ss.SSS"))+">"+"Creating Document on DocDB");
documentClient.createDocument(collectionCache.getSelfLink(), myDocument, null, false);
System.out.println(new DateTime().toString(DateTimeFormat.forPattern("MM-dd-yyyy>HH:mm:ss.SSS"))+">"+"Document Creation Successful");
System.out.flush();
currentThreads.decrementAndGet();
} catch (DocumentClientException e) {
System.out.println("Failed to Upload Document");
e.printStackTrace();
}
}
}
有什么想法我真正的泄漏在哪里吗?有什么地方我需要字符串生成器吗?字符串只是让内存变得有趣吗,我需要给它一个更高的上限来延伸,然后就可以了?
编辑:我做了一些基准测试,这样我实际上可以绘制行为图,以便更好地了解 GC 正在做什么
00000 Threads - 457 MB
01000 Threads - 535 MB
02000 Threads - 545 MB
03000 Threads - 549 MB
04000 Threads - 551 MB
05000 Threads - 555 MB
2 hours later - 595 MB
06000 Threads - 598 MB
07000 Threads - 600 MB
08000 Threads - 602 MB
它看起来是渐近的,但对我来说最有趣的是,当我出去参加 session 和吃午餐时,它决定自行增长 40mb。我与我的团队核实过,在那段时间没有人使用该应用程序。也不知道该怎么做
最佳答案
这是因为你不断地添加字符串。 Java不会自动GC字符串池
String spaceWaster = "";
for (int i = 0; i < 10000; i ++)
spaceWaster += "W";
使用StringBuilder相反
关于Java线程内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38753203/
IntentReceiver 正在泄漏 由于 onDetachedFromWindow 在某些情况下未被调用。 @Override protected void onDetachedFromWind
好吧,我很难追踪这个内存泄漏。运行此脚本时,我没有看到任何内存泄漏,但我的 objectalloc 正在攀升。 Instruments 指向 CGBitmapContextCreateImage >
我编写了一个测试代码来检查如何使用 Instrument(Leaks)。我创建了一个单一 View 应用程序,单击按钮后我加载了一个像这样的新 View ... - (IBAction)btn_clk
我正在使用这个简单的代码并观察单调增加的内存使用量。我正在使用这个小模块将内容转储到磁盘。我观察到它发生在 unicode 字符串上而不是整数上,我做错了什么吗? 当我这样做时: >>> from u
我有以下泄漏的代码。 Instruments 表示,泄漏的是 rssParser 对象。我“刷新”了 XML 提要,它运行了该 block 并且发生了泄漏...... 文件.h @interface
我在我编写的以下代码片段中发现了内存泄漏 NSFileManager *fileManager=[[NSFileManager alloc] init]; fileList=[[fileManager
因此,我正在开发HTML5 / javascript rts游戏。观察一直有几种声音在播放。因此,对我来说,是一段时间后声音听起来像是“崩溃”,并且此浏览器选项卡上的所有声音都停止了工作。我只能通过重
下面是我正在使用的一段代码及其输出。 my $handle; my $enterCount = Devel::Leak::NoteSV($handle); print "$date entry $en
在这篇关于 go-routines 泄漏的帖子之后,https://www.ardanlabs.com/blog/2018/11/goroutine-leaks-the-forgotten-sende
我想知道为什么在执行 ./a.out 后随机得到以下结果。有什么想法我做错了吗?谢谢 http://img710.imageshack.us/img710/8708/trasht.png 最佳答案 正
我正在 Swift 中开发一个应用程序,在呈现捕获我放在一起的二维码的自定义 ViewController 后,我注意到出现了巨大的内存跳跃。 该代码本质上基于以下示例:http://www.appc
下面是我的 javascript 代码片段。它没有按预期运行,请帮我解决这个问题。 function getCurrentLocation() { console.log("insi
我们在生产环境中部署了 3 个代理 Kafka 0.10.1.0。有些应用程序嵌入了 Kafka Producer,它们将应用程序日志发送到某个主题。该主题有 10 个分区,复制因子为 3。 我们观察
我正在使用仪器来检测一些泄漏,但有一些泄漏我无法解决; NSMutableString *textedetails = [[NSMutableString alloc] init];
如果我使用性能工具测试我的代码 - 泄漏,它没有检测到任何泄漏。这是否意味着代码没有泄漏任何内存? 我有一个越狱的 iPhone,我可以监控可用内存。如果有人知道,那就是 SBSettings。我测试
我在从 AddressBook 中获取图像时遇到了很大的问题,下面我粘贴了我的代码。此 imageData 从未被释放,在我的 Allocations Instruments 上它看起来总是在内存中它
- (NSMutableArray *)getArrayValue:(NSArray *)array{ NSMutableArray *valueArray = [NSMutableArra
Instruments 工具说这是一个泄漏,有什么想法吗? 我在 for 循环结束时释放变量对象 在上述方法的开头,这就是我设置变量对象的方式,即自动释放; NSMutableArray *varia
我正在跟踪我的 iOS 应用程序的内存泄漏,我有一个奇怪的泄漏导致我的应用程序崩溃......负责的框架是:CGImageMergeXMPPropsWhithLegacyProps。在某些时候,我的应
我正在尝试使用 NSOperationQueue 在后台线程中执行一个方法,如下所示: NSOperationQueue *queue = [NSOperationQueue new]; NS
我是一名优秀的程序员,十分优秀!