Finding Memory Errors in Java JNI DLL

Finding Memory Errors in Java JNI DLL

David Eisner的头像

I'm evaluating Intel Parallel Inspector 2011 (PIN) with Visual Studio (VS) 2008. I'm trying to find memory errors in a DLL that provides native JNI methods to a Java application (JDK 6), but I'm having some difficulty.

My understanding is that in order to analyze a DLL using PIN, it's necessary to specify a target .exe that loads the DLL. So I wrote a simple Java console app that exercises the DLL and packaged it into a JAR file that can be executed with "java.exe -jar MyTestApp.jar". I have my DLL in the same directory as the java.exe I'm using.

In the VS debug configuration I have 'C:\\path_to\\java.exe' set for the command and '-jar C:\\path_to\\MyTestApp.jar' for the arguments. I start the PIN inspector analysis, the java app runs to completion, and I get a report about Memory Errors. However, my DLL is not listed, only these:

java.dll, java.exe, jvm.dll, msvcr71.dll, ntdll.dll, and zip.dll

I added an intentional bug to my DLL (reading an uninitialized automatic variable), but the bug isn't discovered. I thought perhaps the C compiler's basic runtime checks might be hiding the error (it discovered the bug and brought up a warning dialog at runtime), so I dialed the runtime checks down to 'Default'. It no longer warns me about my intentional bug, but PIN still does not detect it.

What am I doing wrong? Thanks!

12 帖子 / 0 new
最新文章
如需更全面地了解编译器优化,请参阅优化注意事项
Kirill Rogozhin (Intel)的头像

David,

Intel Parallel Inspector doesn't support analyzing of child processes. You can only analyze the target process. Moreover, Java is not supported.
Intel Inspector XE is a more featured variant. It can analyze child processes. However Java is not supported as well. You may try it, but there is no any garantee that the tool will be able to locate your dll.

Regards,
Kirill

David Eisner的头像

Kirill,

Thanks for the response. Java JNI code does not run inside a child process -- it runs in the same process as the java.exe executable. And it is not Java bytecode. Rather, it's native code, written in C/C++ (or assembly) which is compiled into a standard PE32 DLL (using e.g. Visual Studio's C compiler). This DLL is loaded at runtime by the native java.exe process.

Or to put it another way, java.exe is just a native C program using LoadLibrary() to load my DLL when the java bytecode it's interpreting tells it to do so.

-David

Sergey Kostrov的头像
Quoting David Eisner ...Rather, it's native code, written in C/C++ (or assembly) which is compiled into a standard PE32 DLL (using e.g. Visual Studio's C compiler).

Do you have thesource codes for the DLL?

I simply would like to understand if this is your own DLL, orfrom some 3rd-partywithout the source codes.

Best regards,
Sergey

Kirill Rogozhin (Intel)的头像

Yes, Java loads dll in it's process, but it's not supported, there possible some drawbacks. Can you attach your test reproducer to the thread, so I we can play with it and look what's wrong?

Sergey Kostrov的头像
Hi everybody,

I'd like to make a little correction:

Quoting Kirill Rogozhin (Intel) ...Java loads dll in it's process...

...Java loadsdll in its address space...

Best regards,
Sergey

David Eisner的头像

Sergey,

Neither -- it's 3rd-party but with the source code. It's the RXTX library an open source Java library for serial and parallel port communication:http://rxtx.qbang.org/wiki/index.php/FAQ

-David

David Eisner的头像

Kirill,

Thanks for taking the time to look at this. I'll try to post something soon, either today or tomorrow.

-David

David Eisner的头像

I've attached a zip file containing a Visual Studio 2008 project for the DLL code, and a Netbeans project for the Java class, CommTest.java, which uses the RXTXcomm.jar library (which itself uses the JNI rxtxSerial.dll). As I mentioned, the PIN configuration runs 'java.exe -jar C:\path_to\CommTest.jar'. I've also included a Netbeans project for the RXTXcomm.jar library, but you don't really need that. The CommTest.jar in PIN Example/Netbeans/CommTest/dist/ is setup to load the already-compiled RXTXcomm.jar from the lib/ subdirectory.

In the DLL code, I've introduced an intentional bug in termios.c, at the beginning of serial_test() that does an uninitialized variable read, something I assume PIN should catch.

If this is too complicated, let me know and I can try to generate a simpler JAR/DLL that illustrates the problem.

Thanks again.

附件: 

附件尺寸
下载 PIN_Example.zip6.3 MB
Sergey Kostrov的头像
Quoting David Eisner ...it's 3rd-party but with the source code...

As a compromiseyou coulduse MFC-based Memory Leaks detection with a report to an external txt-file.

I'll prepare a Test-Case on how to do it. Would it help?

Best regards,
Sergey

Sergey Kostrov的头像
Quoting Sergey Kostrov
Quoting David Eisner ...it's 3rd-party but with the source code...

As a compromiseyou coulduse MFC-based Memory Leaks detection with a report to an external txt-file...

The following piece of code could be used to enable MFC-based Memory Leaks detection:

	...

	RTtchar *g_pszMemLeaksReportLog = RTU("C:MemLeaksReport.log");

	...

	RThandle hLogFile = RTnull;
	_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );

	_CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_DEBUG );
	hLogFile = ::CreateFile( g_pszMemLeaksReportLog,

				  GENERIC_WRITE, FILE_SHARE_WRITE, RTnull, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, RTnull );

	if( hLogFile == RTnull )

		return;
	_CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );

	_CrtSetReportFile( _CRT_WARN, hLogFile );
	_RPT0( _CRT_WARN, "Processing startedn" );

	...


It is configured tocreate areport( external file )and here is example of how it looks like:

...
Processing started
virtual CTest::~CTest()
virtual CTest::~CTest()
virtual CTest::~CTest()
virtual CTest::~CTest()
virtual CTest::~CTest()
virtual CTest::~CTest()
virtual CTest::~CTest()
virtual CTest::~CTest()
Detected memory leaks!
Dumping objects ->
..\common\prttests.cpp(5943) : {91} normal block at 0x041B0040, 4194304 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
..\common\prttests.cpp(5943) : {89} normal block at 0x03DA0040, 4194304 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
..\common\prttests.cpp(5943) : {87} normal block at 0x03990040, 4194304 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
..\common\prttests.cpp(5943) : {85} normal block at 0x03580040, 4194304 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
..\common\prttests.cpp(5943) : {83} normal block at 0x03170040, 4194304 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
..\common\prttests.cpp(5943) : {81} normal block at 0x02D60040, 4194304 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
..\common\prttests.cpp(5943) : {79} normal block at 0x02950040, 4194304 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
..\common\prttests.cpp(5943) : {77} normal block at 0x02140040, 4194304 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.
Processing Completed
...

Sergey Kostrov的头像

Here is updated set of codes you could use:

	// Header files

	...

	#define CRTDBG_MAP_ALLOC

	#include 

	#include 

	...
	// Initialization

	...

	TCHAR *g_pszMemLeaksReportLog = _T("C:MemLeaksReport.log");

	...

	HANDLE hLogFile = NULL;
	_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );

	_CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_DEBUG );
	hLogFile = ::CreateFile( g_pszMemLeaksReportLog,

				  GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );

	if( hLogFile == NULL )

		return;
	_CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );

	_CrtSetReportFile( _CRT_WARN, hLogFile );
	_RPT0( _CRT_WARN, "Processing startedn" );

	...
	// Your processing...
	// Final cleanups

	...

	_CrtDumpMemoryLeaks();

	_RPT0( _CRT_WARN, "Processing Completedn" );
	if( hLogFile != NULL )

	{

		::CloseHandle( hLogFile );

		hLogFile = NULL;

	}

	...

These libraries should be used ( Debug versions )

msvcrtd.lib
msvcurtd.lib if Unicode Character Set is used

登陆并发表评论。