Error attaching to core file: Can't attach to the core file

原文:http://dikar.iteye.com/blog/643436

如题,我这里简单说下我现在离线分析java内存的方式,所谓离线,就是需要dump出正在运行的java系统中的一些运行时堆栈数据,然后拿到线下来分析,分析可以包括内存,线程,GC等等,同时不会对正在运行的生产环境的机器造成很大的影响,对应着离线分析,当然是在线分析了,这个我在后面会尝试下,因为离线分析有些场景还是模拟不出来,需要借助LR来模拟压力,查看在线的java程序运行情况了。

            首先一个简单的问题,如何dump出java运行时堆栈,这个SUN就提供了很好的工具,位于JAVA_HOME/bin目录下的jmap(java memory map之意),如果需要dump出当前运行的java进程的堆栈数据,则首先需要获得该java进程的进程ID,在linux下可以使用

Java代码 

 收藏代码

  1. ps -aux  
  2.   
  3. ps -ef | grep java  

或者使用jdk自带的一个工具jps,例如

Java代码 

 收藏代码

  1. /JAVA_HOME/bin/jps  

找到了当前运行的java进程的id后,就可以对正在运行的java进程使用jmap工具进行dump了,例如使用以下命令:

Java代码 

 收藏代码

  1. JAVA_HOME/bin/jmap  -dump:format=b,file=heap.bin <pid>   

其中file = heap.bin的意思是dump出的文件名叫heap.bin, 当然你可以选择你喜欢的名字,我这里选择叫*.bin是为了后面使用方便,<pid>表示你需要dump的java进程的id。

这里需要注意的是,记住dump的进程是java进程,不会是jboss的进程,weblogic的进程等。dump过程中机器load可能会升高,但是在我这里测试发现load升的不是特别快,同时dump时需要的磁盘空间也比较大,例如我这里测试的几个系统,分别是500M 800M 1500M  3000M,所以确保你运行jmap命令时所在的目录中的磁盘空间足够,当然现在的系统磁盘空间都比较大。

以上是在java进程还存活的时候进行的dump,有的时候我们的java进程crash后,会生成一个core.pid文件,这个core.pid文件还不能直接被我们的java 内存分析工具使用,需要将其转换为java 内存分析工具可以读的文件(例如使用jmap工具dump出的heap.bin文件就是很多java 内存分析工具可以读的文件格式)。将core.pid文件转换为jmap工具dump出的文件格式还可以继续使用jmap工具,这个的说明可以见我前几篇中的一个转载(Create Java heapdumps with the help of core dumps ),这里我在补充点

Java代码 

 收藏代码

  1. jmap -heap:format=b [java binary] [core dump file]  
  2.   
  3.   
  4. 64位下可以指定使用64位模式  
  5.   
  6. jmap -d64  -dump:format=b [java binary] [core dump file]  

需要说明一下,使用jmap转换core.pid文件时,当文件格式比较大时,可能大于2G的时候就不能执行成功(我转换3G文件大小的时候没有成功)而报出

Error attaching to core file: Can't attach to the core file

查过sun的bug库中,这个bug还没有被修复,我想还是由于32位下用户进程寻址大小限制在2G的范围内引起的,在64位系统和64位jdk版本中,转换3G文件应该没有什么大的问题(有机会有环境得需要测试下)。如果有兴趣分析jmap转换不成功的同学,可以使用如下命令来分析跟踪命令的执行轨迹,例如使用

Java代码 

 收藏代码

  1. strace  jmap -heap:format=b [java binary] [core dum  
  2. p]  

 对于strace的命令的说明,同样可以参考我前几篇文章中的一个 strace命令用法

同时对于core.pid文件的调试我也补充一下, 其中>>表示命令提示符

Java代码 

 收藏代码

  1. >>gdb JAVA_HOME/bin/java  core.pid  
  2.   
  3. >>bt  

bt后就可以看到生成core.pid文件时,系统正在执行的一个操作,例如是哪个so文件正在执行等。

好了说了这么多,上面都是怎么生成java 运行期DUMP文件的,接下来我们就进入分析阶段,为了分析这个dump出的文件,需要将这个文件弄到你的分析程序所在的机器上,例如可以是windows上,linux上,这个和你使用的分析工具以及使用的操作系统有关。不管使用什么系统,总是需要把生产环境下打出的dump文件搞到你的分析机器上,由于dump出的文件经常会比较大,例如达到2G,这么大的文件不是很好的从生产环境拉下来,因此使用FTP的方式把文件拖到分析机器上,同时由于单个文件很大,因此为了快速的将文件下载到分析机器,我们可以使用分而治之的思想,先将文件切割为小文件下载,然后在合并为一个大文件即可,还好linux提供了很方便的工具,例如使用如下命令

Java代码 

 收藏代码

  1. $ split -b 300m heap.bin  
  2.   
  3.  $ cat x* > heap.bin  

在上面的 split 命令行中的 “300m” 表示分割后的每个文件为 300MB,“heap.bin” 为待分割的dump文件,分割后的文件自动命名为 xaa,xab,xac等 

cat 命令可将这些分割后的文件合并为一个文件,例如将所有x开头的文件合并为heap.bin

如果我们是利用一个中间层的FTP服务器来保存数据的,那么我们还需要连接这个FTP服务器把合并后的文件拉下来,在windows下我推荐使用一个工具,速度很快而且简单,

winscp   http://winscp.net/eng/docs/lang:chs

好了分析的文件终于经过一翻周折到了你的分析机器上,现在我们就可以使用分析工具来分析这个dump出的程序了,这里我主要是分析内存的问题,所以我说下我选择的内存分析工具,我这里使用的是开源的由SAP 和IBM 支持的一个内存分析工具

Memory Analyzer (MAT)

http://www.eclipse.org/mat/

我建议下载 Stand-alone Eclipse RCP 版本,不要装成eclipse的插件,因为这个分析起来还是很耗内存。

下载好了,解压开来就可以直接使用了(基于eclipse的),打开以后,在菜单栏中选择打开文件,选择你刚刚的dump文件,然后一路的next就可以了,最后你会看到一个报告,这个报告里会告诉你可能的内存泄露的点,以及内存中对象的一个分布,关于mat的使用请参考官方说明,当然你也可以自己徜徉在学习的海洋中 。

对于dump文件的分析还可以使用jdk中提供的一个jhat工具来查看,不过这个很耗内存,而且默认的内存大小不够,还需要增加参数设置内存大小才能分析出,不过我看了下分析出的结果不是很满意,而且这个用起来很慢。还是推荐使用mat 。

构建您的第一个应用程序 按照教程进行作 这是 Electron 教程的第 2 部分。 先决条件 构建您的第一个应用程序 使用预加载脚本 添加功能 打包您的应用程序 发布和更新 学习目标 在本教程的这一部分中,您将学习如何设置 Electron 项目 并编写一个最小的入门应用程序。在本节结束时, 您应该能够在开发模式下运行一个有效的 Electron 应用程序,来自 您的终端。 设置项目 避免 WSL 如果您使用的是 Windows 计算机,请不要使用适用于 Linux 的 Windows 子系统 (WSL) 在遵循本教程时,因为您在尝试执行 应用。 初始化 npm 项目 电子应用程序使用 npm 搭建脚手架,文件为 package.json 作为切入点。首先创建一个文件夹并初始化一个 npm 包 在其中有 .npm init npm 纱 mkdir my-electron-app && cd my-electron-app npm init 此命令将提示您在package.json中配置一些字段。 出于本教程的目的,需要遵循一些规则: 入口点应该是(你很快就会创建该文件)。main.js author、license 和 description 可以是任何值,但以后打包时将是必需的。 使用常规文件夹安装依赖项node_modules Electron 的打包工具链要求文件夹物理位于磁盘上,在 npm 安装节点依赖项的方式。默认情况下,Yarn Berry 和 pnpm 都使用替代安装策略。node_modules 因此,如果您使用 那些包管理器。 然后,将 Electron 安装到应用程序的 devDependencies 中,这是外部 生产中不需要仅开发包依赖项。 为什么 Electron 是开发依赖项? 这似乎有悖常理,因为你的生产代码正在运行 Electron API。在引擎盖下, Electron 的 JavaScript API 绑定到包含其实现的二进制文件。包装步骤 Electron 处理此二进制文件的捆绑,无需将其指定为生产 屬地。 npm 纱 npm install electron --save-dev 警告 为了正确安装 Electron,您需要确保其生命周期 脚本能够运行。这意味着避免在 npm 上使用标志,并允许列入在其他包管理器上运行构建脚本的权限。postinstall--ignore-scriptselectron 这可能会在 Electron 的未来版本中改变。有关更多详细信息,请参阅 electron/rfcs#22。 初始化包后,您的package.json文件应该如下所示 并安装 Electron。您现在还应该有一个文件夹,其中包含 Electron 可执行文件,以及指定 要安装的确切依赖项版本。node_modulespackage-lock.json package.json { "name": "my-electron-app", "version": "1.0.0", "description": "Hello World!", "main": "main.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "Jane Doe", "license": "MIT", "devDependencies": { "electron": "23.1.3" } } 高级 Electron 安装步骤 如果直接安装 Electron 失败,请参阅我们的高级安装文档,了解有关下载镜像、代理和故障排除步骤的说明。 添加 .gitignore .gitignore 文件指定要避免跟踪的文件和目录与 Git。您应该将 GitHub 的 Node.js gitignore 模板的副本放入项目的根文件夹中,以避免提交项目的文件夹。node_modules 运行 Electron 应用程序 进一步阅读 阅读 Electron 的流程模型文档以更好地了解 Electron 的多个流程如何协同工作。 您在 package.json 中定义的主脚本是任何Electron 应用程序的入口点。该脚本控制主进程,该进程在Node.js环境中运行,负责控制应用程序的生命周期、显示本机接口、执行特权作以及管理渲染器进程(稍后会详细介绍)。 在创建您的第一个 Electron 应用程序之前,您将首先使用一个简单的脚本来确保您的main 进程入口点配置正确。在根文件夹中创建一个文件使用一行代码:main.js main.js console.log('Hello from Electron 👋') 因为 Electron 的主进程是一个Node.js运行时,所以你可以执行任意的Node.js代码(你甚至可以把它用作 REPL)。要执行这个脚本,add 到你package.json的 scripts 字段中的命令。这个命令会告诉 Electron 可执行文件在当前目录中查找主script 并在开发模式下运行它。electronelectron .start package.json { "name": "my-electron-app", "version": "1.0.0", "description": "Hello World!", "main": "main.js", "scripts": { "start": "electron .", "test": "echo \"Error: no test specified\" && exit 1" }, "author": "Jane Doe", "license": "MIT", "devDependencies": { "electron": "23.1.3" } } npm Yarn npm run start Your terminal should print out . Congratulations, you have executed your first line of code in Electron! Next, you will learn how to create user interfaces with HTML and load that into a native window.Hello from Electron 👋 Loading a web page into a BrowserWindow In Electron, each window displays a web page that can be loaded either from a local HTML file or a remote web address. For this example, you will be loading in a local file. Start by creating a barebones web page in an file in the root folder of your project:index.html index.html <!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP --> <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'" /> <meta http-equiv="X-Content-Security-Policy" content="default-src 'self'; script-src 'self'" /> <title>Hello from Electron renderer!</title> </head> <body> <h1>Hello from Electron renderer!</h1> <p>👋</p> </body> </html> Now that you have a web page, you can load it into an Electron BrowserWindow. Replace the contents of your file with the following code. We will explain each highlighted block separately.main.js main.js const { app, BrowserWindow } = require('electron') const createWindow = () => { const win = new BrowserWindow({ width: 800, height: 600 }) win.loadFile('index.html') } app.whenReady().then(() => { createWindow() }) Importing modules main.js (Line 1) const { app, BrowserWindow } = require('electron') In the first line, we are importing two Electron modules with CommonJS module syntax: app, which controls your application's event lifecycle. BrowserWindow, which creates and manages app windows. Module capitalization conventions Typed import aliases ES Modules in Electron ECMAScript modules (i.e. using to load a module) are supported in Electron as of Electron 28. You can find more information about the state of ESM in Electron and how to use them in our app in our ESM guide.import Writing a reusable function to instantiate windows The function loads your web page into a new BrowserWindow instance:createWindow() main.js (Lines 3-10) const createWindow = () => { const win = new BrowserWindow({ width: 800, height: 600 }) win.loadFile('index.html') } Calling your function when the app is ready main.js (Lines 12-14) app.whenReady().then(() => { createWindow() }) Many of Electron's core modules are Node.js event emitters that adhere to Node's asynchronous event-driven architecture. The app module is one of these emitters. In Electron, BrowserWindows can only be created after the app module's ready event is fired. You can wait for this event by using the app.whenReady() API and calling once its promise is fulfilled.createWindow() info You typically listen to Node.js events by using an emitter's function..on + app.on('ready', () => { - app.whenReady().then(() => { createWindow() }) However, Electron exposes as a helper specifically for the event to avoid subtle pitfalls with directly listening to that event in particular. See electron/electron#21972 for details.app.whenReady()ready At this point, running your Electron application's command should successfully open a window that displays your web page!start Each web page your app displays in a window will run in a separate process called a renderer process (or simply renderer for short). Renderer processes have access to the same JavaScript APIs and tooling you use for typical front-end web development, such as using webpack to bundle and minify your code or React to build your user interfaces. Managing your app's window lifecycle Application windows behave differently on each operating system. Rather than enforce these conventions by default, Electron gives you the choice to implement them in your app code if you wish to follow them. You can implement basic window conventions by listening for events emitted by the app and BrowserWindow modules. Process-specific control flow Checking against Node's process.platform variable can help you to run code conditionally on certain platforms. Note that there are only three possible platforms that Electron can run in: (Windows), (Linux), and (macOS).win32linuxdarwin Quit the app when all windows are closed (Windows & Linux) On Windows and Linux, closing all windows will generally quit an application entirely. To implement this pattern in your Electron app, listen for the app module's window-all-closed event, and call app.quit() to exit your app if the user is not on macOS. app.on('window-all-closed', () => { if (process.platform !== 'darwin') app.quit() }) Open a window if none are open (macOS) In contrast, macOS apps generally continue running even without any windows open. Activating the app when no windows are available should open a new one. To implement this feature, listen for the app module's activate event, and call your existing method if no BrowserWindows are open.createWindow() Because windows cannot be created before the event, you should only listen for events after your app is initialized. Do this by only listening for activate events inside your existing callback.readyactivatewhenReady() app.whenReady().then(() => { createWindow() app.on('activate', () => { if (BrowserWindow.getAllWindows().length === 0) createWindow() }) }) Final starter code docs/fiddles/tutorial-first-app (39.0.0) main.js index.html const { app, BrowserWindow } = require('electron/main') const createWindow = () => { const win = new BrowserWindow({ width: 800, height: 600 }) win.loadFile('index.html') } app.whenReady().then(() => { createWindow() app.on('activate', () => { if (BrowserWindow.getAllWindows().length === 0) { createWindow() } }) }) app.on('window-all-closed', () => { if (process.platform !== 'darwin') { app.quit() } }) Optional: Debugging from VS Code If you want to debug your application using VS Code, you need to attach VS Code to both the main and renderer processes. Here is a sample configuration for you to run. Create a launch.json configuration in a new folder in your project:.vscode .vscode/launch.json { "version": "0.2.0", "compounds": [ { "name": "Main + renderer", "configurations": ["Main", "Renderer"], "stopAll": true } ], "configurations": [ { "name": "Renderer", "port": 9222, "request": "attach", "type": "chrome", "webRoot": "${workspaceFolder}" }, { "name": "Main", "type": "node", "request": "launch", "cwd": "${workspaceFolder}", "runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron", "windows": { "runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron.cmd" }, "args": [".", "--remote-debugging-port=9222"], "outputCapture": "std", "console": "integratedTerminal" } ] } The "Main + renderer" option will appear when you select "Run and Debug" from the sidebar, allowing you to set breakpoints and inspect all the variables among other things in both the main and renderer processes. What we have done in the file is to create 3 configurations:launch.json Main is used to start the main process and also expose port 9222 for remote debugging (). This is the port that we will use to attach the debugger for the . Because the main process is a Node.js process, the type is set to .--remote-debugging-port=9222Renderernode Renderer is used to debug the renderer process. Because the main process is the one that creates the process, we have to "attach" to it () instead of creating a new one. The renderer process is a web one, so the debugger we have to use is ."request": "attach"chrome Main + renderer is a compound task that executes the previous ones simultaneously. caution Because we are attaching to a process in , it is possible that the first lines of your code will be skipped as the debugger will not have had enough time to connect before they are being executed. You can work around this by refreshing the page or setting a timeout before executing the code in development mode.Renderer Further reading If you want to dig deeper in the debugging area, the following guides provide more information: Application Debugging DevTools Extensions 总结 电子应用程序是使用 npm 包设置的。应该安装 Electron 可执行文件 ,可以使用 package.json文件。devDependencies 可执行文件运行在package.json属性中找到的 JavaScript 入口点。 该文件控制 Electron 的主进程,该进程运行 Node.js 的实例,并且是 负责应用的生命周期,显示本机接口,执行特权作, 以及管理渲染器进程。main 渲染器进程(或简称渲染器)负责显示图形内容。您可以 通过将网页指向网址或本地 HTML 文件,将网页加载到渲染器中。 渲染器的行为与常规网页非常相似,并且可以访问相同的 Web API。 在本教程的下一节中,我们将学习如何使用 特权 API 以及如何在进程之间进行通信。 总结并为我写出完整的步骤
最新发布
11-01
在调试核心转储文件(core dump)时,如果 Windbg 提示 "OpenDumpFile failed" 错误,通常是由于以下原因之一导致的:文件格式不兼容、文件损坏、路径问题或权限不足等。以下是详细的分析与解决方法: 1. **确认核心转储文件格式** Windbg 要求核心转储文件为标准的 Windows minidump 格式。如果该文件是通过非标准方式生成的(例如 Linux 环境下生成的核心转储),则无法被 Windbg 正确识别[^1]。可以使用 `dumpchk` 工具检查文件是否符合 minidump 格式。 2. **验证文件完整性** 如果核心转储文件在生成或传输过程中出现中断或损坏,也可能导致加载失败。尝试重新生成核心转储文件,并确保其完整无损[^1]。 3. **检查文件路径和访问权限** Windbg 需要对目标 core 文件具有读取权限。若文件位于受限制的目录中或路径包含特殊字符,可能导致打开失败。建议将文件移动到简单路径(如 `C:\Dumps\`)并以管理员身份运行 Windbg[^1]。 4. **使用正确的 Windbg 版本** 不同版本的 Windbg 对 minidump 文件的支持程度不同。若使用的是旧版调试工具包,可能会存在兼容性问题。请更新至最新版本的 [Windows SDK](https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/) 或安装 [WinDbg Preview](https://www.microsoft.com/store/productId/9PGJGD53TN8G)[^1]。 5. **尝试其他调试器** 若 Windbg 仍无法打开文件,可尝试使用 Visual Studio 或其他支持 minidump 的调试工具进行加载,以进一步判断是否为 Windbg 自身的问题[^1]。 6. **查看详细错误信息** 在 Windbg 中执行 `.lasterror` 命令可以获取更具体的错误代码,有助于定位问题根源。根据返回的 HRESULT 值查找对应的系统错误描述[^1]。 ### 示例操作 若怀疑文件损坏,可使用如下命令行工具验证 minidump 文件: ```bash dumpchk core.dmp ``` 若输出显示文件结构正常,则应继续排查环境配置问题。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值