Skip to main content

Tips on creating a small JNI jar on Windows

Posted by kohsuke on March 19, 2008 at 11:25 AM PDT

I created a small library to manipulate Windows processes the other day, and someone showed interest in how to create a small footprint DLL in Windows. So this blog is to explain you what I did.

The main idea behind cutting down the size of DLL is to avoid linking the Visual C++ runtime. In many cases, you'd only use JNI to talk to other DLLs (most often to kernel32.dll or ntdll.dll — IOW, system calls), and in those situations, this is quite feasible.

For this to work, you'll do the following:

  1. Add /NODEFAULTLIB to the linker option, indicating you don't want to link to the C runtime.
  2. Add /GS- /GX- and /GR- as these C++ features rely on the C runtime.
  3. Don't use any of the functions that are exposed by the C runtime. I have yet to figure out how to mechanically determine exactly what's in C-runtime and what's not, but generally speaking all-lower case function calls like strcpy, malloc or memcpy are out (but then, Kernel exposes some all-lower case functions, like lstrcpy so it's really case-by-case.) All C++ features, like runtime exception handling, runtime type information, and the new/delete operators are gone, too.
  4. Add _DllMainCRTStartup instead of DllMain, so that you don't rely on the start-up code in C-runtime. See the following:
    extern "C" BOOL WINAPI _DllMainCRTStartup(HANDLE  hDllHandle, DWORD   dwReason, LPVOID  lpreserved) {
        return TRUE;
    }

That's it. If the linker runs successfully, you should see a substantially smaller DLL. When you accidentally end up using functions from the C runtime library, the linker often fails with an error saying "unresolved symbol: _main". When that happens, you need to turn on the /VERBOSE linker option and see which dependency is causing the C runtime to kick in.

Kernel does offer the basic string manipulation libraries, so those are useful when you don't have the C runtime. Ditto for memory allocation functions, but those are often somewhat awkward.

I've also read somewhere that you can pack the PE header by using the smaller alignment, but I couldn't figure out how to convince the linker to do that, or whether that is really legal or not.

In conclusion, if you are using the C runtime, then you should seriously question if some 20KB improvement in the footprint is worth your productivity drop, but if you are not using the C runtime, these relatively mechanical steps would give you the satisfaction of a compact DLL (plus the satisfaction of getting one step close to the inner working on Windows.)

Related Topics >>

Comments

I'm wondering how did you work around creating and working with C++ objects w/o the C++ runtime. Or did you mean C runtime only? Dmitri

Yes, your ability to do real C++ is significantly crippled without C and C++ runtime.