Problem with gcj/boehm-gc on windows

David Peroutka djp@volny.cz
Sun Aug 24 17:39:00 GMT 2003


Hi,

I've tried to port my GCJ-based application from linux/ia32 to windows, and
I've found a strange problem with garbage collector; it can be reproduced
using the following code:

---- gltest.cc ----
/* compile with `gcj gltest.cc -o gltest.exe -lopengl32 -lglu32 -lgdi32` */
#include <stdio.h>
#include <gcj/cni.h>
#include <GL/gl.h>
#include <GL/glu.h>

extern "C" void JvRunMain (jclass klass, int argc, const char **argv);

extern "C" {
extern int GC_print_stats;
extern int GC_dont_gc;
extern int GC_no_dls;
extern int GC_no_win32_dlls;
}

int main(int argc, const char **argv)
{
	printf("Hello\n");
	if (argc < 0) {
		gluErrorString(0); // (un)comment this to see the difference
	}

	GC_print_stats = 1;
//	GC_no_win32_dlls = 0;
//	GC_dont_precollect = 0;
	JvCreateJavaVM(NULL);
	printf("Goodbye\n");
	return 0;
}
---- end of gltest.cc ----

On my computer, the program execution took 30 seconds.  If you comment out the
`gluErrorString` call, the execution is instant...

I've tried this code with Mohan's gcc33-20030802.zip, and then with my own
build, based on gcc-3.3.1, replacing gc with gc6.2alpha6, and gc6.3alpha1,
only to achieve the same result.

After that, I've found that the problem is caused by a very large memory
region (128MB) which is included in the static root set of the garbage
collector.  It seems that the region corresponds to the video memory on my
graphics card (I tried that on another computer with 64MB video memory, and
the region size was, well, 64MB then).

Since I've found no clean way how to detect that the large memory region
should not be included in the root set, I've modified the inclusion test with
the following workaround:

dyn_load.c/GC_register_dynamic_libraries:

    if (buf.RegionSize < 0x2000000 /* ignore large (>32MB) regions */
    	&& buf.State == MEM_COMMIT
        && (protect == PAGE_EXECUTE_READWRITE
            || protect == PAGE_READWRITE)
        && !GC_is_heap_base(buf.AllocationBase)) {
...

Note that the attributes of the large region in question are:
State == MEM_COMMIT, Type == MEM_MAPPED, Protect == PAGE_READWRITE

Any better ideas?


This workaround solved the problem with the `gltest` example, but not with my
"real" application.  After successful startup the application crashed with
"Too many root sets" message.

After analysing the application's root set, I've found that there is _huge_
number (>1000) of 4096-sized memory regions included in the static root set.

The application itself is designed to create real-time particle effects, using
a combination of SWT/OpenGL/CG libs, so it's rather resource intensive; but
I've no idea why it generates so many non-continuous root sections.  Anyway,
after increasing MAX_ROOT_SETS to 4096, it works.

Realizing that the huge root set is rescanned for every gcollect_inner
(try_to_collect_inner, respectively), I've tried to exclude root sections
which do not belong to the image of my (statically linked) application, but,
apparently, with no luck.  Some simple test programs I've created are working
with slightly modifed `GC_no_win32_dlls` execution path, but the big
application always crashed (randomly).

It'd be ideal to create a static permanent (non-temp) root set, excluding any
writeable sections from dlls.  Is it possible?


Thanks a lot,

--
David



More information about the Java mailing list