Make-lang.in (JAVA_MANFILES): Add doc/gc-analyze.1.
gcc/java: 2007-02-15 David Daney <ddaney@avtrex.com> * Make-lang.in (JAVA_MANFILES): Add doc/gc-analyze.1. (java.maintainer-clean):Add gc-analyze.1. (.INTERMEDIATE): Add gc-analyze.pod. (gc-analyze.pod): New rule. (java.install-man): Install gc-analyze.1 * gcj.texi: Add new section for the gc-analyze program. libjava: 2007-02-15 Johannes Schmidt <jschmidt@avtrex.com> David Daney <ddaney@avtrex.com> * configure.ac: Create vm-tools-packages file. Add gnu/gcj/tools/gc_analyze to standard.omit and vm-tools-packages. Check for /proc/self/maps. * Makefile.am (bin_PROGRAMS): Added gc-analyze. (gc_analyze_SOURCES): New. (gc_analyze_LDFLAGS): New. (gc_analyze_LINK): New. (gc_analyze_LDADD): New. (gc_analyze_DEPENDENCIES): New. (nat_source_files): Add gnu/gcj/util/natGCInfo.cc. * Makefile.in: Regenerated. * configure: Regenerated. * include/config.h.in: Regenerated. * sources.am: Regenerated. * scripts/makemake.tcl: Don't include gc-analyze classes in libgcj. * gnu/gcj/tools/gc_analyze/SymbolLookup.java: New. * gnu/gcj/tools/gc_analyze/ObjectMap.java: New. * gnu/gcj/tools/gc_analyze/MemoryMap.java: New. * gnu/gcj/tools/gc_analyze/SymbolTable.java: New. * gnu/gcj/tools/gc_analyze/BlockMap.java: New. * gnu/gcj/tools/gc_analyze/BytePtr.java: New. * gnu/gcj/tools/gc_analyze/ItemList.java: New. * gnu/gcj/tools/gc_analyze/ToolPrefix.java: New. * gnu/gcj/tools/gc_analyze/MemoryAnalyze.java: New. * gnu/gcj/util/GCInfo.java: New. * gnu/gcj/util/GCInfo.h: New. * gnu/gcj/util/natGCInfo.cc: New. * gnu/gcj/util/UtilPermission.java: New. * gnu/gcj/util/UtilPermission.h: New. * classpath/tools/gnu/gcj/tools/gc_analyze/SymbolTable.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/ObjectMap$ObjectItem.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryMap$RangeComparator.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/BlockMap$PtrMarks.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryMap$Range.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/BlockMap.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/BytePtr.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryAnalyze$SubstringComparator.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/ItemList.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/ToolPrefix.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryAnalyze.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryAnalyze$1$Info.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryAnalyze$1.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryAnalyze$2.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryAnalyze$3.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryAnalyze$4.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryAnalyze$OptionParser.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/BlockMap$SizeKind.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/SymbolLookup.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/ObjectMap.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryMap.class: New. * classpath/lib/gnu/gcj/util/GCInfo.class: New. * classpath/lib/gnu/gcj/util/UtilPermission.class: New. libjava/classpath: 2007-02-15 David Daney <ddaney@avtrex.com> * tools/Makefile.am (TOOLS_ZIP): Add classes from vm-tools-packages. * tools/Makefile.in: Regenerated. From-SVN: r122007
This commit is contained in:
parent
31429fbc3c
commit
7f40378f06
51 changed files with 2783 additions and 39 deletions
|
@ -1,3 +1,12 @@
|
|||
2007-02-15 David Daney <ddaney@avtrex.com>
|
||||
|
||||
* Make-lang.in (JAVA_MANFILES): Add doc/gc-analyze.1.
|
||||
(java.maintainer-clean):Add gc-analyze.1.
|
||||
(.INTERMEDIATE): Add gc-analyze.pod.
|
||||
(gc-analyze.pod): New rule.
|
||||
(java.install-man): Install gc-analyze.1
|
||||
* gcj.texi: Add new section for the gc-analyze program.
|
||||
|
||||
2007-02-07 Andrew Haley <aph@redhat.com>
|
||||
|
||||
* class.c (uncache_this_class_ref): New.
|
||||
|
|
|
@ -139,7 +139,7 @@ java.pdf: doc/gcj.pdf
|
|||
java.html: $(build_htmldir)/java/index.html
|
||||
JAVA_MANFILES = doc/gcj.1 doc/jcf-dump.1 doc/gij.1 \
|
||||
doc/jv-convert.1 doc/grmic.1 doc/grmiregistry.1 \
|
||||
doc/gcj-dbtool.1
|
||||
doc/gcj-dbtool.1 doc/gc-analyze.1
|
||||
|
||||
java.man: $(JAVA_MANFILES)
|
||||
|
||||
|
@ -208,6 +208,7 @@ java.maintainer-clean:
|
|||
-rm -f $(docobjdir)/grmic.1
|
||||
-rm -f $(docobjdir)/grmiregistry.1
|
||||
-rm -f $(docobjdir)/gcj-dbtool.1
|
||||
-rm -f $(docobjdir)/gc-analyze.1
|
||||
#
|
||||
# Stage hooks:
|
||||
# The main makefile has already created stage?/java.
|
||||
|
@ -318,7 +319,7 @@ $(build_htmldir)/java/index.html: $(TEXI_JAVA_FILES)
|
|||
$(TEXI2HTML) -I $(gcc_docdir)/include -I $(srcdir)/java -o $(@D) $<
|
||||
|
||||
.INTERMEDIATE: gcj.pod jcf-dump.pod gij.pod \
|
||||
jv-convert.pod grmic.pod grmiregistry.pod gcj-dbtool.pod
|
||||
jv-convert.pod grmic.pod grmiregistry.pod gcj-dbtool.pod gc-analyze.pod
|
||||
|
||||
gcj.pod: java/gcj.texi
|
||||
-$(TEXI2POD) -D gcj < $< > $@
|
||||
|
@ -334,15 +335,17 @@ grmiregistry.pod: java/gcj.texi
|
|||
-$(TEXI2POD) -D grmiregistry < $< > $@
|
||||
gcj-dbtool.pod: java/gcj.texi
|
||||
-$(TEXI2POD) -D gcj-dbtool < $< > $@
|
||||
gc-analyze.pod: java/gcj.texi
|
||||
-$(TEXI2POD) -D gc-analyze < $< > $@
|
||||
|
||||
# Install the man pages.
|
||||
java.install-man: installdirs \
|
||||
$(DESTDIR)$(man1dir)/$(JAVA_INSTALL_NAME)$(man1ext) \
|
||||
$(JAVA_TARGET_INDEPENDENT_BIN_TOOLS:%=doc/%.1) \
|
||||
doc/gij.1 doc/jv-convert.1 doc/grmic.1 doc/grmiregistry.1 \
|
||||
doc/gcj-dbtool.1
|
||||
doc/gcj-dbtool.1 doc/gc-analyze.1
|
||||
for tool in $(JAVA_TARGET_INDEPENDENT_BIN_TOOLS) \
|
||||
gij jv-convert grmic grmiregistry gcj-dbtool ; do \
|
||||
gij jv-convert grmic grmiregistry gcj-dbtool gc-analyze ; do \
|
||||
tool_transformed_name=`echo $$tool|sed '$(program_transform_name)'`; \
|
||||
man_name=$(DESTDIR)$(man1dir)/$${tool_transformed_name}$(man1ext); \
|
||||
rm -f $$man_name ; \
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
@c the word ``Java'.
|
||||
|
||||
@c When this manual is copyrighted.
|
||||
@set copyrights-gcj 2001, 2002, 2003, 2004, 2005
|
||||
@set copyrights-gcj 2001, 2002, 2003, 2004, 2005, 2006, 2007
|
||||
|
||||
@c Versions
|
||||
@set which-gcj GCC-@value{version-GCC}
|
||||
|
@ -79,6 +79,8 @@ man page gfdl(7).
|
|||
Generate stubs for Remote Method Invocation.
|
||||
* grmiregistry: (gcj)Invoking grmiregistry.
|
||||
The remote object registry.
|
||||
* gc-analyze: (gcj)Invoking gc-analyze.
|
||||
Analyze Garbage Collector (GC) memory dumps.
|
||||
@end direntry
|
||||
@end format
|
||||
|
||||
|
@ -125,6 +127,7 @@ files and object files, and it can read both Java source code and
|
|||
* Invoking jv-convert:: Converting from one encoding to another
|
||||
* Invoking grmic:: Generate stubs for Remote Method Invocation.
|
||||
* Invoking grmiregistry:: The remote object registry.
|
||||
* Invoking gc-analyze:: Analyze Garbage Collector (GC) memory dumps.
|
||||
* About CNI:: Description of the Compiled Native Interface
|
||||
* System properties:: Modifying runtime behavior of the libgcj library
|
||||
* Resources:: Where to look for more information
|
||||
|
@ -1412,6 +1415,89 @@ Print version information, then exit.
|
|||
@c man end
|
||||
|
||||
|
||||
@node Invoking gc-analyze
|
||||
@chapter Invoking gc-analyze
|
||||
|
||||
@c man title gc-analyze Analyze Garbage Collector (GC) memory dumps
|
||||
|
||||
@c man begin SYNOPSIS gc-analyze
|
||||
@command{gc-analyze} [@option{OPTION}] @dots{} [@var{file}]
|
||||
@ignore
|
||||
[@option{-v}]
|
||||
[@option{--verbose}]
|
||||
[@option{-p} @var{tool-prefix}]
|
||||
[@option{-d} @var{directory}]
|
||||
[@option{--version}]
|
||||
[@option{--help}]
|
||||
@end ignore
|
||||
@c man end
|
||||
|
||||
@c man begin DESCRIPTION gc-analyze
|
||||
|
||||
@command{gc-analyze} prints an analysis of a GC memory dump to
|
||||
standard out.
|
||||
|
||||
The memory dumps may be created by calling
|
||||
@code{gnu.gcj.util.GCInfo.enumerate(String namePrefix)} from java
|
||||
code. A memory dump will be created on an out of memory condition if
|
||||
@code{gnu.gcj.util.GCInfo.setOOMDump(String namePrefix)} is called
|
||||
before the out of memory occurs.
|
||||
|
||||
Running this program will create two files: @file{TestDump001} and
|
||||
@file{TestDump001.bytes}.
|
||||
|
||||
@example
|
||||
import gnu.gcj.util.*;
|
||||
import java.util.*;
|
||||
|
||||
public class GCDumpTest
|
||||
@{
|
||||
static public void main(String args[])
|
||||
@{
|
||||
ArrayList<String> l = new ArrayList<String>(1000);
|
||||
|
||||
for (int i = 1; i < 1500; i++) @{
|
||||
l.add("This is string #" + i);
|
||||
@}
|
||||
GCInfo.enumerate("TestDump");
|
||||
@}
|
||||
@}
|
||||
@end example
|
||||
|
||||
The memory dump may then be displayed by running:
|
||||
|
||||
@example
|
||||
gc-analyze -v TestDump001
|
||||
@end example
|
||||
|
||||
@c FIXME: Add real information here.
|
||||
@c This really isn't much more than the --help output.
|
||||
|
||||
@c man end
|
||||
|
||||
@c man begin OPTIONS gc-analyze
|
||||
|
||||
@table @gcctabopt
|
||||
@item --verbose
|
||||
@itemx -v
|
||||
Verbose output.
|
||||
|
||||
@item -p @var{tool-prefix}
|
||||
Prefix added to the names of the @command{nm} and @command{readelf} commands.
|
||||
|
||||
@item -d @var{directory}
|
||||
Directory that contains the executable and shared libraries used when
|
||||
the dump was generated.
|
||||
|
||||
@item --help
|
||||
Print a help message, then exit.
|
||||
|
||||
@item --version
|
||||
Print version information, then exit.
|
||||
@end table
|
||||
|
||||
@c man end
|
||||
|
||||
@node About CNI
|
||||
@chapter About CNI
|
||||
|
||||
|
|
|
@ -1,3 +1,59 @@
|
|||
2007-02-15 Johannes Schmidt <jschmidt@avtrex.com>
|
||||
David Daney <ddaney@avtrex.com>
|
||||
|
||||
* configure.ac: Create vm-tools-packages file. Add
|
||||
gnu/gcj/tools/gc_analyze to standard.omit and vm-tools-packages.
|
||||
Check for /proc/self/maps.
|
||||
* Makefile.am (bin_PROGRAMS): Added gc-analyze.
|
||||
(gc_analyze_SOURCES): New.
|
||||
(gc_analyze_LDFLAGS): New.
|
||||
(gc_analyze_LINK): New.
|
||||
(gc_analyze_LDADD): New.
|
||||
(gc_analyze_DEPENDENCIES): New.
|
||||
(nat_source_files): Add gnu/gcj/util/natGCInfo.cc.
|
||||
* Makefile.in: Regenerated.
|
||||
* configure: Regenerated.
|
||||
* include/config.h.in: Regenerated.
|
||||
* sources.am: Regenerated.
|
||||
* scripts/makemake.tcl: Don't include gc-analyze classes in libgcj.
|
||||
* gnu/gcj/tools/gc_analyze/SymbolLookup.java: New.
|
||||
* gnu/gcj/tools/gc_analyze/ObjectMap.java: New.
|
||||
* gnu/gcj/tools/gc_analyze/MemoryMap.java: New.
|
||||
* gnu/gcj/tools/gc_analyze/SymbolTable.java: New.
|
||||
* gnu/gcj/tools/gc_analyze/BlockMap.java: New.
|
||||
* gnu/gcj/tools/gc_analyze/BytePtr.java: New.
|
||||
* gnu/gcj/tools/gc_analyze/ItemList.java: New.
|
||||
* gnu/gcj/tools/gc_analyze/ToolPrefix.java: New.
|
||||
* gnu/gcj/tools/gc_analyze/MemoryAnalyze.java: New.
|
||||
* gnu/gcj/util/GCInfo.java: New.
|
||||
* gnu/gcj/util/GCInfo.h: New.
|
||||
* gnu/gcj/util/natGCInfo.cc: New.
|
||||
* gnu/gcj/util/UtilPermission.java: New.
|
||||
* gnu/gcj/util/UtilPermission.h: New.
|
||||
* classpath/tools/gnu/gcj/tools/gc_analyze/SymbolTable.class: New.
|
||||
* classpath/tools/gnu/gcj/tools/gc_analyze/ObjectMap$ObjectItem.class: New.
|
||||
* classpath/tools/gnu/gcj/tools/gc_analyze/MemoryMap$RangeComparator.class: New.
|
||||
* classpath/tools/gnu/gcj/tools/gc_analyze/BlockMap$PtrMarks.class: New.
|
||||
* classpath/tools/gnu/gcj/tools/gc_analyze/MemoryMap$Range.class: New.
|
||||
* classpath/tools/gnu/gcj/tools/gc_analyze/BlockMap.class: New.
|
||||
* classpath/tools/gnu/gcj/tools/gc_analyze/BytePtr.class: New.
|
||||
* classpath/tools/gnu/gcj/tools/gc_analyze/MemoryAnalyze$SubstringComparator.class: New.
|
||||
* classpath/tools/gnu/gcj/tools/gc_analyze/ItemList.class: New.
|
||||
* classpath/tools/gnu/gcj/tools/gc_analyze/ToolPrefix.class: New.
|
||||
* classpath/tools/gnu/gcj/tools/gc_analyze/MemoryAnalyze.class: New.
|
||||
* classpath/tools/gnu/gcj/tools/gc_analyze/MemoryAnalyze$1$Info.class: New.
|
||||
* classpath/tools/gnu/gcj/tools/gc_analyze/MemoryAnalyze$1.class: New.
|
||||
* classpath/tools/gnu/gcj/tools/gc_analyze/MemoryAnalyze$2.class: New.
|
||||
* classpath/tools/gnu/gcj/tools/gc_analyze/MemoryAnalyze$3.class: New.
|
||||
* classpath/tools/gnu/gcj/tools/gc_analyze/MemoryAnalyze$4.class: New.
|
||||
* classpath/tools/gnu/gcj/tools/gc_analyze/MemoryAnalyze$OptionParser.class: New.
|
||||
* classpath/tools/gnu/gcj/tools/gc_analyze/BlockMap$SizeKind.class: New.
|
||||
* classpath/tools/gnu/gcj/tools/gc_analyze/SymbolLookup.class: New.
|
||||
* classpath/tools/gnu/gcj/tools/gc_analyze/ObjectMap.class: New.
|
||||
* classpath/tools/gnu/gcj/tools/gc_analyze/MemoryMap.class: New.
|
||||
* classpath/lib/gnu/gcj/util/GCInfo.class: New.
|
||||
* classpath/lib/gnu/gcj/util/UtilPermission.class: New.
|
||||
|
||||
2007-02-15 David Daney <ddaney@avtrex.com>
|
||||
|
||||
* gnu/java/net/PlainSocketImpl.h: Regenerate.
|
||||
|
|
|
@ -73,7 +73,7 @@ db_pathtail = gcj-$(gcc_version)/$(db_name)
|
|||
if NATIVE
|
||||
bin_PROGRAMS = jv-convert gij grmic grmiregistry gcj-dbtool \
|
||||
gappletviewer gjarsigner gkeytool gjar gjavah gnative2ascii \
|
||||
gorbd grmid gserialver gtnameserv
|
||||
gorbd grmid gserialver gtnameserv gc-analyze
|
||||
|
||||
## It is convenient to actually build and install the default database
|
||||
## when gcj-dbtool is available.
|
||||
|
@ -647,6 +647,20 @@ gcj_dbtool_LDADD = gnu/gcj/tools/gcj_dbtool.lo -L$(here)/.libs libgcj.la
|
|||
## linking this program.
|
||||
gcj_dbtool_DEPENDENCIES = gnu/gcj/tools/gcj_dbtool.lo libgcj.la libgcj.spec
|
||||
|
||||
gc_analyze_SOURCES =
|
||||
|
||||
## We need -nodefaultlibs because we want to avoid gcj's `-lgcj'. We
|
||||
## need this because we are explicitly using libtool to link using the
|
||||
## `.la' file.
|
||||
gc_analyze_LDFLAGS = --main=gnu.gcj.tools.gc_analyze.MemoryAnalyze \
|
||||
-rpath $(toolexeclibdir) -shared-libgcc $(THREADLDFLAGS)
|
||||
gc_analyze_LINK = $(GCJLINK)
|
||||
## See jv_convert_LDADD.
|
||||
gc_analyze_LDADD = -L$(here)/.libs libgcj-tools.la libgcj.la
|
||||
## Depend on the spec file to make sure it is up to date before
|
||||
## linking this program.
|
||||
gc_analyze_DEPENDENCIES = libgcj-tools.la libgcj.la libgcj.spec
|
||||
|
||||
gij_SOURCES =
|
||||
## We need -nodefaultlibs because we want to avoid gcj's `-lgcj'. We
|
||||
## need this because we are explicitly using libtool to link using the
|
||||
|
@ -831,6 +845,7 @@ gnu/gcj/runtime/natSharedLibLoader.cc \
|
|||
gnu/gcj/runtime/natSystemClassLoader.cc \
|
||||
gnu/gcj/runtime/natStringBuffer.cc \
|
||||
gnu/gcj/util/natDebug.cc \
|
||||
gnu/gcj/util/natGCInfo.cc \
|
||||
gnu/java/lang/natMainThread.cc \
|
||||
gnu/java/lang/management/natVMClassLoadingMXBeanImpl.cc \
|
||||
gnu/java/lang/management/natVMCompilationMXBeanImpl.cc \
|
||||
|
|
|
@ -51,7 +51,7 @@ target_triplet = @target@
|
|||
@NATIVE_TRUE@ gjar$(EXEEXT) gjavah$(EXEEXT) \
|
||||
@NATIVE_TRUE@ gnative2ascii$(EXEEXT) gorbd$(EXEEXT) \
|
||||
@NATIVE_TRUE@ grmid$(EXEEXT) gserialver$(EXEEXT) \
|
||||
@NATIVE_TRUE@ gtnameserv$(EXEEXT)
|
||||
@NATIVE_TRUE@ gtnameserv$(EXEEXT) gc-analyze$(EXEEXT)
|
||||
@BUILD_ECJ1_TRUE@libexecsub_PROGRAMS = ecjx$(EXEEXT)
|
||||
@ANONVERSCRIPT_TRUE@am__append_5 = -Wl,--version-script=$(srcdir)/libgcj.ver
|
||||
@USING_GCC_TRUE@am__append_6 = $(WARNINGS)
|
||||
|
@ -305,7 +305,7 @@ am__libgcj_la_SOURCES_DIST = prims.cc jni.cc jvmti.cc exception.cc \
|
|||
gnu/gcj/runtime/natSharedLibLoader.cc \
|
||||
gnu/gcj/runtime/natSystemClassLoader.cc \
|
||||
gnu/gcj/runtime/natStringBuffer.cc gnu/gcj/util/natDebug.cc \
|
||||
gnu/java/lang/natMainThread.cc \
|
||||
gnu/gcj/util/natGCInfo.cc gnu/java/lang/natMainThread.cc \
|
||||
gnu/java/lang/management/natVMClassLoadingMXBeanImpl.cc \
|
||||
gnu/java/lang/management/natVMCompilationMXBeanImpl.cc \
|
||||
gnu/java/lang/management/natVMGarbageCollectorMXBeanImpl.cc \
|
||||
|
@ -368,7 +368,7 @@ am__objects_2 = gnu/classpath/jdwp/natVMFrame.lo \
|
|||
gnu/gcj/runtime/natSharedLibLoader.lo \
|
||||
gnu/gcj/runtime/natSystemClassLoader.lo \
|
||||
gnu/gcj/runtime/natStringBuffer.lo gnu/gcj/util/natDebug.lo \
|
||||
gnu/java/lang/natMainThread.lo \
|
||||
gnu/gcj/util/natGCInfo.lo gnu/java/lang/natMainThread.lo \
|
||||
gnu/java/lang/management/natVMClassLoadingMXBeanImpl.lo \
|
||||
gnu/java/lang/management/natVMCompilationMXBeanImpl.lo \
|
||||
gnu/java/lang/management/natVMGarbageCollectorMXBeanImpl.lo \
|
||||
|
@ -438,6 +438,8 @@ am_ecjx_OBJECTS =
|
|||
ecjx_OBJECTS = $(am_ecjx_OBJECTS)
|
||||
am_gappletviewer_OBJECTS =
|
||||
gappletviewer_OBJECTS = $(am_gappletviewer_OBJECTS)
|
||||
am_gc_analyze_OBJECTS =
|
||||
gc_analyze_OBJECTS = $(am_gc_analyze_OBJECTS)
|
||||
am_gcj_dbtool_OBJECTS = gnu/gcj/tools/gcj_dbtool/natMain.$(OBJEXT)
|
||||
gcj_dbtool_OBJECTS = $(am_gcj_dbtool_OBJECTS)
|
||||
am__gen_from_JIS_SOURCES_DIST = gnu/gcj/convert/gen-from-JIS.c \
|
||||
|
@ -501,23 +503,23 @@ SOURCES = $(lib_gnu_awt_xlib_la_SOURCES) $(libgcj_tools_la_SOURCES) \
|
|||
$(libgcj_la_SOURCES) $(EXTRA_libgcj_la_SOURCES) \
|
||||
$(libgcj_bc_la_SOURCES) $(libgij_la_SOURCES) \
|
||||
$(libjvm_la_SOURCES) $(ecjx_SOURCES) $(gappletviewer_SOURCES) \
|
||||
$(gcj_dbtool_SOURCES) $(gen_from_JIS_SOURCES) $(gij_SOURCES) \
|
||||
$(gjar_SOURCES) $(gjarsigner_SOURCES) $(gjavah_SOURCES) \
|
||||
$(gkeytool_SOURCES) $(gnative2ascii_SOURCES) $(gorbd_SOURCES) \
|
||||
$(grmic_SOURCES) $(grmid_SOURCES) $(grmiregistry_SOURCES) \
|
||||
$(gserialver_SOURCES) $(gtnameserv_SOURCES) \
|
||||
$(jv_convert_SOURCES)
|
||||
$(gc_analyze_SOURCES) $(gcj_dbtool_SOURCES) \
|
||||
$(gen_from_JIS_SOURCES) $(gij_SOURCES) $(gjar_SOURCES) \
|
||||
$(gjarsigner_SOURCES) $(gjavah_SOURCES) $(gkeytool_SOURCES) \
|
||||
$(gnative2ascii_SOURCES) $(gorbd_SOURCES) $(grmic_SOURCES) \
|
||||
$(grmid_SOURCES) $(grmiregistry_SOURCES) $(gserialver_SOURCES) \
|
||||
$(gtnameserv_SOURCES) $(jv_convert_SOURCES)
|
||||
DIST_SOURCES = $(lib_gnu_awt_xlib_la_SOURCES) \
|
||||
$(libgcj_tools_la_SOURCES) $(am__libgcj_la_SOURCES_DIST) \
|
||||
$(EXTRA_libgcj_la_SOURCES) $(libgcj_bc_la_SOURCES) \
|
||||
$(libgij_la_SOURCES) $(libjvm_la_SOURCES) $(ecjx_SOURCES) \
|
||||
$(gappletviewer_SOURCES) $(gcj_dbtool_SOURCES) \
|
||||
$(am__gen_from_JIS_SOURCES_DIST) $(gij_SOURCES) \
|
||||
$(gjar_SOURCES) $(gjarsigner_SOURCES) $(gjavah_SOURCES) \
|
||||
$(gkeytool_SOURCES) $(gnative2ascii_SOURCES) $(gorbd_SOURCES) \
|
||||
$(grmic_SOURCES) $(grmid_SOURCES) $(grmiregistry_SOURCES) \
|
||||
$(gserialver_SOURCES) $(gtnameserv_SOURCES) \
|
||||
$(jv_convert_SOURCES)
|
||||
$(gappletviewer_SOURCES) $(gc_analyze_SOURCES) \
|
||||
$(gcj_dbtool_SOURCES) $(am__gen_from_JIS_SOURCES_DIST) \
|
||||
$(gij_SOURCES) $(gjar_SOURCES) $(gjarsigner_SOURCES) \
|
||||
$(gjavah_SOURCES) $(gkeytool_SOURCES) $(gnative2ascii_SOURCES) \
|
||||
$(gorbd_SOURCES) $(grmic_SOURCES) $(grmid_SOURCES) \
|
||||
$(grmiregistry_SOURCES) $(gserialver_SOURCES) \
|
||||
$(gtnameserv_SOURCES) $(jv_convert_SOURCES)
|
||||
RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
|
||||
html-recursive info-recursive install-data-recursive \
|
||||
install-exec-recursive install-info-recursive \
|
||||
|
@ -1344,7 +1346,9 @@ gnu/gcj/tools/gcj_dbtool/Main.java
|
|||
|
||||
gnu_gcj_tools_gcj_dbtool_header_files = $(patsubst %.java,%.h,$(gnu_gcj_tools_gcj_dbtool_source_files))
|
||||
gnu_gcj_util_source_files = \
|
||||
gnu/gcj/util/Debug.java
|
||||
gnu/gcj/util/Debug.java \
|
||||
gnu/gcj/util/GCInfo.java \
|
||||
gnu/gcj/util/UtilPermission.java
|
||||
|
||||
gnu_gcj_util_header_files = $(patsubst %.java,%.h,$(gnu_gcj_util_source_files))
|
||||
gnu_gcj_xlib_source_files = \
|
||||
|
@ -7818,6 +7822,13 @@ gcj_dbtool_LDFLAGS = --main=gnu.gcj.tools.gcj_dbtool.Main \
|
|||
gcj_dbtool_LINK = $(GCJLINK)
|
||||
gcj_dbtool_LDADD = gnu/gcj/tools/gcj_dbtool.lo -L$(here)/.libs libgcj.la
|
||||
gcj_dbtool_DEPENDENCIES = gnu/gcj/tools/gcj_dbtool.lo libgcj.la libgcj.spec
|
||||
gc_analyze_SOURCES =
|
||||
gc_analyze_LDFLAGS = --main=gnu.gcj.tools.gc_analyze.MemoryAnalyze \
|
||||
-rpath $(toolexeclibdir) -shared-libgcc $(THREADLDFLAGS)
|
||||
|
||||
gc_analyze_LINK = $(GCJLINK)
|
||||
gc_analyze_LDADD = -L$(here)/.libs libgcj-tools.la libgcj.la
|
||||
gc_analyze_DEPENDENCIES = libgcj-tools.la libgcj.la libgcj.spec
|
||||
gij_SOURCES =
|
||||
gij_LDFLAGS = -rpath $(libdir)/gcj-$(gcc_version) -rpath $(toolexeclibdir) \
|
||||
-shared-libgcc $(THREADLDFLAGS)
|
||||
|
@ -7947,6 +7958,7 @@ gnu/gcj/runtime/natSharedLibLoader.cc \
|
|||
gnu/gcj/runtime/natSystemClassLoader.cc \
|
||||
gnu/gcj/runtime/natStringBuffer.cc \
|
||||
gnu/gcj/util/natDebug.cc \
|
||||
gnu/gcj/util/natGCInfo.cc \
|
||||
gnu/java/lang/natMainThread.cc \
|
||||
gnu/java/lang/management/natVMClassLoadingMXBeanImpl.cc \
|
||||
gnu/java/lang/management/natVMCompilationMXBeanImpl.cc \
|
||||
|
@ -8360,6 +8372,8 @@ gnu/gcj/util/$(DEPDIR)/$(am__dirstamp):
|
|||
@: > gnu/gcj/util/$(DEPDIR)/$(am__dirstamp)
|
||||
gnu/gcj/util/natDebug.lo: gnu/gcj/util/$(am__dirstamp) \
|
||||
gnu/gcj/util/$(DEPDIR)/$(am__dirstamp)
|
||||
gnu/gcj/util/natGCInfo.lo: gnu/gcj/util/$(am__dirstamp) \
|
||||
gnu/gcj/util/$(DEPDIR)/$(am__dirstamp)
|
||||
gnu/java/lang/$(am__dirstamp):
|
||||
@$(mkdir_p) gnu/java/lang
|
||||
@: > gnu/java/lang/$(am__dirstamp)
|
||||
|
@ -8694,6 +8708,9 @@ ecjx$(EXEEXT): $(ecjx_OBJECTS) $(ecjx_DEPENDENCIES)
|
|||
gappletviewer$(EXEEXT): $(gappletviewer_OBJECTS) $(gappletviewer_DEPENDENCIES)
|
||||
@rm -f gappletviewer$(EXEEXT)
|
||||
$(gappletviewer_LINK) $(gappletviewer_LDFLAGS) $(gappletviewer_OBJECTS) $(gappletviewer_LDADD) $(LIBS)
|
||||
gc-analyze$(EXEEXT): $(gc_analyze_OBJECTS) $(gc_analyze_DEPENDENCIES)
|
||||
@rm -f gc-analyze$(EXEEXT)
|
||||
$(gc_analyze_LINK) $(gc_analyze_LDFLAGS) $(gc_analyze_OBJECTS) $(gc_analyze_LDADD) $(LIBS)
|
||||
gnu/gcj/tools/gcj_dbtool/$(am__dirstamp):
|
||||
@$(mkdir_p) gnu/gcj/tools/gcj_dbtool
|
||||
@: > gnu/gcj/tools/gcj_dbtool/$(am__dirstamp)
|
||||
|
@ -8826,6 +8843,8 @@ mostlyclean-compile:
|
|||
-rm -f gnu/gcj/tools/gcj_dbtool/natMain.$(OBJEXT)
|
||||
-rm -f gnu/gcj/util/natDebug.$(OBJEXT)
|
||||
-rm -f gnu/gcj/util/natDebug.lo
|
||||
-rm -f gnu/gcj/util/natGCInfo.$(OBJEXT)
|
||||
-rm -f gnu/gcj/util/natGCInfo.lo
|
||||
-rm -f gnu/gcj/xlib/lib_gnu_awt_xlib_la-natClip.$(OBJEXT)
|
||||
-rm -f gnu/gcj/xlib/lib_gnu_awt_xlib_la-natClip.lo
|
||||
-rm -f gnu/gcj/xlib/lib_gnu_awt_xlib_la-natColormap.$(OBJEXT)
|
||||
|
@ -9035,6 +9054,7 @@ distclean-compile:
|
|||
@AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/runtime/$(DEPDIR)/natSystemClassLoader.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/tools/gcj_dbtool/$(DEPDIR)/natMain.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/util/$(DEPDIR)/natDebug.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/util/$(DEPDIR)/natGCInfo.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/xlib/$(DEPDIR)/lib_gnu_awt_xlib_la-natClip.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/xlib/$(DEPDIR)/lib_gnu_awt_xlib_la-natColormap.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/xlib/$(DEPDIR)/lib_gnu_awt_xlib_la-natDisplay.Plo@am__quote@
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2007-02-15 David Daney <ddaney@avtrex.com>
|
||||
|
||||
* tools/Makefile.am (TOOLS_ZIP): Add classes from vm-tools-packages.
|
||||
* tools/Makefile.in: Regenerated.
|
||||
|
||||
2007-02-15 Gary Benson <gbenson@redhat.com>
|
||||
|
||||
* javax/management/AttributeList.java: Updated.
|
||||
|
|
BIN
libjava/classpath/lib/gnu/gcj/util/GCInfo.class
Normal file
BIN
libjava/classpath/lib/gnu/gcj/util/GCInfo.class
Normal file
Binary file not shown.
BIN
libjava/classpath/lib/gnu/gcj/util/UtilPermission.class
Normal file
BIN
libjava/classpath/lib/gnu/gcj/util/UtilPermission.class
Normal file
Binary file not shown.
|
@ -155,12 +155,19 @@ $(TOOLS_ZIP): $(TOOLS_JAVA_FILES)
|
|||
## mkdir classes asm
|
||||
find $(srcdir)/external/asm -name '*.java' -print > asm.lst
|
||||
find $(srcdir)/gnu/classpath/tools -name '*.java' -print > classes.lst
|
||||
cat classes.lst asm.lst > all-classes.lst
|
||||
if [ -f $(top_builddir)/../vm-tools-packages ]; then \
|
||||
for pkg in `cat $(top_builddir)/../vm-tools-packages`; do \
|
||||
$(FIND) $(top_srcdir)/../$$pkg -follow -name '*.java' -print >> vm-tools.lst; \
|
||||
done \
|
||||
else \
|
||||
echo -n > vm-tools.lst; \
|
||||
fi
|
||||
cat classes.lst asm.lst vm-tools.lst > all-classes.lst
|
||||
if JAVA_MAINTAINER_MODE
|
||||
## Compile ASM separately as it is latin-1 encoded.
|
||||
AC=`echo $(JCOMPILER) | sed -e 's/UTF-8/ISO-8859-1/g'`; \
|
||||
$$AC -g -w -d $(srcdir)/asm @asm.lst
|
||||
$(JCOMPILER) -g -w -d $(srcdir)/classes @classes.lst
|
||||
$(JCOMPILER) -g -w -d $(srcdir)/classes @classes.lst @vm-tools.lst
|
||||
## Copy over tools resource files.
|
||||
@list=`cd $(top_srcdir)/resource && find gnu/classpath/tools -name \*.properties -print`; \
|
||||
for p in $$list; do \
|
||||
|
|
|
@ -1079,10 +1079,17 @@ dist-hook:
|
|||
$(TOOLS_ZIP): $(TOOLS_JAVA_FILES)
|
||||
find $(srcdir)/external/asm -name '*.java' -print > asm.lst
|
||||
find $(srcdir)/gnu/classpath/tools -name '*.java' -print > classes.lst
|
||||
cat classes.lst asm.lst > all-classes.lst
|
||||
if [ -f $(top_builddir)/../vm-tools-packages ]; then \
|
||||
for pkg in `cat $(top_builddir)/../vm-tools-packages`; do \
|
||||
$(FIND) $(top_srcdir)/../$$pkg -follow -name '*.java' -print >> vm-tools.lst; \
|
||||
done \
|
||||
else \
|
||||
echo -n > vm-tools.lst; \
|
||||
fi
|
||||
cat classes.lst asm.lst vm-tools.lst > all-classes.lst
|
||||
@JAVA_MAINTAINER_MODE_TRUE@ AC=`echo $(JCOMPILER) | sed -e 's/UTF-8/ISO-8859-1/g'`; \
|
||||
@JAVA_MAINTAINER_MODE_TRUE@ $$AC -g -w -d $(srcdir)/asm @asm.lst
|
||||
@JAVA_MAINTAINER_MODE_TRUE@ $(JCOMPILER) -g -w -d $(srcdir)/classes @classes.lst
|
||||
@JAVA_MAINTAINER_MODE_TRUE@ $(JCOMPILER) -g -w -d $(srcdir)/classes @classes.lst @vm-tools.lst
|
||||
@JAVA_MAINTAINER_MODE_TRUE@ @list=`cd $(top_srcdir)/resource && find gnu/classpath/tools -name \*.properties -print`; \
|
||||
@JAVA_MAINTAINER_MODE_TRUE@ for p in $$list; do \
|
||||
@JAVA_MAINTAINER_MODE_TRUE@ dirname=classes/`dirname $$p`; \
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
192
libjava/configure
vendored
192
libjava/configure
vendored
|
@ -5087,6 +5087,12 @@ if test "$use_x_awt" != yes; then
|
|||
echo gnu/java/awt/peer/x >> standard.omit
|
||||
fi
|
||||
|
||||
# Tools that need to be compiled against classpath's tools classes
|
||||
for package in gnu/gcj/tools/gc_analyze ; do
|
||||
echo $package >> standard.omit
|
||||
echo $package >> vm-tools-packages
|
||||
done
|
||||
|
||||
if test -z "${with_multisubdir}"; then
|
||||
builddotdot=.
|
||||
else
|
||||
|
@ -6024,7 +6030,7 @@ test x"$pic_mode" = xno && libtool_flags="$libtool_flags --prefer-non-pic"
|
|||
case $host in
|
||||
*-*-irix6*)
|
||||
# Find out which ABI we are using.
|
||||
echo '#line 6027 "configure"' > conftest.$ac_ext
|
||||
echo '#line 6033 "configure"' > conftest.$ac_ext
|
||||
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
|
||||
(eval $ac_compile) 2>&5
|
||||
ac_status=$?
|
||||
|
@ -7066,7 +7072,7 @@ if test "${enable_sjlj_exceptions+set}" = set; then
|
|||
:
|
||||
else
|
||||
cat > conftest.$ac_ext << EOF
|
||||
#line 7069 "configure"
|
||||
#line 7075 "configure"
|
||||
struct S { ~S(); };
|
||||
void bar();
|
||||
void foo()
|
||||
|
@ -7819,7 +7825,7 @@ ac_x_header_dirs='
|
|||
/usr/openwin/share/include'
|
||||
|
||||
if test "$ac_x_includes" = no; then
|
||||
# Guess where to find include files, by looking for Intrinsic.h.
|
||||
# Guess where to find include files, by looking for Xlib.h.
|
||||
# First, try using that file with no special directory specified.
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
|
@ -7827,7 +7833,7 @@ _ACEOF
|
|||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
#include <X11/Intrinsic.h>
|
||||
#include <X11/Xlib.h>
|
||||
_ACEOF
|
||||
if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
|
||||
(eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
|
||||
|
@ -7854,7 +7860,7 @@ else
|
|||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
for ac_dir in $ac_x_header_dirs; do
|
||||
if test -r "$ac_dir/X11/Intrinsic.h"; then
|
||||
if test -r "$ac_dir/X11/Xlib.h"; then
|
||||
ac_x_includes=$ac_dir
|
||||
break
|
||||
fi
|
||||
|
@ -7868,7 +7874,7 @@ if test "$ac_x_libraries" = no; then
|
|||
# See if we find them without any special options.
|
||||
# Don't add to $LIBS permanently.
|
||||
ac_save_LIBS=$LIBS
|
||||
LIBS="-lXt $LIBS"
|
||||
LIBS="-lX11 $LIBS"
|
||||
if test x$gcc_no_link = xyes; then
|
||||
{ { echo "$as_me:$LINENO: error: Link tests are not allowed after GCC_NO_EXECUTABLES." >&5
|
||||
echo "$as_me: error: Link tests are not allowed after GCC_NO_EXECUTABLES." >&2;}
|
||||
|
@ -7880,11 +7886,11 @@ _ACEOF
|
|||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
#include <X11/Intrinsic.h>
|
||||
#include <X11/Xlib.h>
|
||||
int
|
||||
main ()
|
||||
{
|
||||
XtMalloc (0)
|
||||
XrmInitialize ()
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
|
@ -10395,6 +10401,37 @@ cat >>confdefs.h <<\_ACEOF
|
|||
#define HAVE_PROC_SELF_EXE 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
|
||||
echo "$as_me:$LINENO: checking for /proc/self/maps" >&5
|
||||
echo $ECHO_N "checking for /proc/self/maps... $ECHO_C" >&6
|
||||
if test "${ac_cv_file__proc_self_maps+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
test "$cross_compiling" = yes &&
|
||||
{ { echo "$as_me:$LINENO: error: cannot check for file existence when cross compiling" >&5
|
||||
echo "$as_me: error: cannot check for file existence when cross compiling" >&2;}
|
||||
{ (exit 1); exit 1; }; }
|
||||
if test -r "/proc/self/maps"; then
|
||||
ac_cv_file__proc_self_maps=yes
|
||||
else
|
||||
ac_cv_file__proc_self_maps=no
|
||||
fi
|
||||
fi
|
||||
echo "$as_me:$LINENO: result: $ac_cv_file__proc_self_maps" >&5
|
||||
echo "${ECHO_T}$ac_cv_file__proc_self_maps" >&6
|
||||
if test $ac_cv_file__proc_self_maps = yes; then
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE__PROC_SELF_MAPS 1
|
||||
_ACEOF
|
||||
|
||||
|
||||
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define HAVE_PROC_SELF_MAPS 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
|
||||
else
|
||||
|
@ -10405,6 +10442,11 @@ cat >>confdefs.h <<\_ACEOF
|
|||
#define HAVE_PROC_SELF_EXE 1
|
||||
_ACEOF
|
||||
|
||||
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define HAVE_PROC_SELF_MAPS 1
|
||||
_ACEOF
|
||||
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
@ -16815,7 +16857,7 @@ if test "${have_tls+set}" = set; then
|
|||
else
|
||||
|
||||
if test "$cross_compiling" = yes; then
|
||||
if test x$gcc_no_link = xyes; then
|
||||
if test x$gcc_no_link = xyes; then
|
||||
{ { echo "$as_me:$LINENO: error: Link tests are not allowed after GCC_NO_EXECUTABLES." >&5
|
||||
echo "$as_me: error: Link tests are not allowed after GCC_NO_EXECUTABLES." >&2;}
|
||||
{ (exit 1); exit 1; }; }
|
||||
|
@ -16855,6 +16897,7 @@ fi
|
|||
rm -f conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
|
||||
|
||||
else
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
__thread int a; int b; int main() { return a = b; }
|
||||
|
@ -16870,7 +16913,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
|
|||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); }; }; then
|
||||
save_LDFLAGS="$LDFLAGS"
|
||||
chktls_save_LDFLAGS="$LDFLAGS"
|
||||
LDFLAGS="-static $LDFLAGS"
|
||||
if test x$gcc_no_link = xyes; then
|
||||
{ { echo "$as_me:$LINENO: error: Link tests are not allowed after GCC_NO_EXECUTABLES." >&5
|
||||
|
@ -16942,7 +16985,134 @@ have_tls=yes
|
|||
fi
|
||||
rm -f conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
LDFLAGS="$save_LDFLAGS"
|
||||
LDFLAGS="$chktls_save_LDFLAGS"
|
||||
if test $have_tls = yes; then
|
||||
chktls_save_CFLAGS="$CFLAGS"
|
||||
thread_CFLAGS=failed
|
||||
for flag in '' '-pthread' '-lpthread'; do
|
||||
CFLAGS="$flag $chktls_save_CFLAGS"
|
||||
if test x$gcc_no_link = xyes; then
|
||||
{ { echo "$as_me:$LINENO: error: Link tests are not allowed after GCC_NO_EXECUTABLES." >&5
|
||||
echo "$as_me: error: Link tests are not allowed after GCC_NO_EXECUTABLES." >&2;}
|
||||
{ (exit 1); exit 1; }; }
|
||||
fi
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
#include <pthread.h>
|
||||
void *g(void *d) { return NULL; }
|
||||
int
|
||||
main ()
|
||||
{
|
||||
pthread_t t; pthread_create(&t,NULL,g,NULL);
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
rm -f conftest.$ac_objext conftest$ac_exeext
|
||||
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
|
||||
(eval $ac_link) 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } &&
|
||||
{ ac_try='test -z "$ac_c_werror_flag"
|
||||
|| test ! -s conftest.err'
|
||||
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); }; } &&
|
||||
{ ac_try='test -s conftest$ac_exeext'
|
||||
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); }; }; then
|
||||
thread_CFLAGS="$flag"
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
fi
|
||||
rm -f conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
if test "X$thread_CFLAGS" != Xfailed; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
CFLAGS="$chktls_save_CFLAGS"
|
||||
if test "X$thread_CFLAGS" != Xfailed; then
|
||||
CFLAGS="$thread_CFLAGS $chktls_save_CFLAGS"
|
||||
if test "$cross_compiling" = yes; then
|
||||
{ { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
|
||||
See \`config.log' for more details." >&5
|
||||
echo "$as_me: error: cannot run test program while cross compiling
|
||||
See \`config.log' for more details." >&2;}
|
||||
{ (exit 1); exit 1; }; }
|
||||
else
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
#include <pthread.h>
|
||||
__thread int a;
|
||||
static int *a_in_other_thread;
|
||||
static void *
|
||||
thread_func (void *arg)
|
||||
{
|
||||
a_in_other_thread = &a;
|
||||
return (void *)0;
|
||||
}
|
||||
int
|
||||
main ()
|
||||
{
|
||||
pthread_t thread;
|
||||
void *thread_retval;
|
||||
int *a_in_main_thread;
|
||||
if (pthread_create (&thread, (pthread_attr_t *)0,
|
||||
thread_func, (void *)0))
|
||||
return 0;
|
||||
a_in_main_thread = &a;
|
||||
if (pthread_join (thread, &thread_retval))
|
||||
return 0;
|
||||
return (a_in_other_thread == a_in_main_thread);
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
rm -f conftest$ac_exeext
|
||||
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
|
||||
(eval $ac_link) 2>&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } && { ac_try='./conftest$ac_exeext'
|
||||
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); }; }; then
|
||||
have_tls=yes
|
||||
else
|
||||
echo "$as_me: program exited with status $ac_status" >&5
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
( exit $ac_status )
|
||||
have_tls=no
|
||||
fi
|
||||
rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
|
||||
fi
|
||||
CFLAGS="$chktls_save_CFLAGS"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo "$as_me: program exited with status $ac_status" >&5
|
||||
echo "$as_me: failed program was:" >&5
|
||||
|
|
|
@ -295,6 +295,12 @@ if test "$use_x_awt" != yes; then
|
|||
echo gnu/java/awt/peer/x >> standard.omit
|
||||
fi
|
||||
|
||||
# Tools that need to be compiled against classpath's tools classes
|
||||
for package in gnu/gcj/tools/gc_analyze ; do
|
||||
echo $package >> standard.omit
|
||||
echo $package >> vm-tools-packages
|
||||
done
|
||||
|
||||
if test -z "${with_multisubdir}"; then
|
||||
builddotdot=.
|
||||
else
|
||||
|
@ -1012,10 +1018,14 @@ else
|
|||
if test x"$cross_compiling" = x"no"; then
|
||||
AC_CHECK_FILES(/proc/self/exe, [
|
||||
AC_DEFINE(HAVE_PROC_SELF_EXE, 1, [Define if you have /proc/self/exe])])
|
||||
AC_CHECK_FILES(/proc/self/maps, [
|
||||
AC_DEFINE(HAVE_PROC_SELF_MAPS, 1,
|
||||
[Define if you have /proc/self/maps])])
|
||||
else
|
||||
case $host in
|
||||
*-linux*)
|
||||
AC_DEFINE(HAVE_PROC_SELF_EXE, 1, [Define if you have /proc/self/exe])
|
||||
AC_DEFINE(HAVE_PROC_SELF_MAPS, 1, [Define if you have /proc/self/maps])
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
|
218
libjava/gnu/gcj/tools/gc_analyze/BlockMap.java
Normal file
218
libjava/gnu/gcj/tools/gc_analyze/BlockMap.java
Normal file
|
@ -0,0 +1,218 @@
|
|||
/* BlockMap.java -- Container for information on GC maintained memory blocks.
|
||||
Copyright (C) 2007 Free Software Foundation
|
||||
|
||||
This file is part of libgcj.
|
||||
|
||||
This software is copyrighted work licensed under the terms of the
|
||||
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
|
||||
details. */
|
||||
|
||||
package gnu.gcj.tools.gc_analyze;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
class BlockMap
|
||||
{
|
||||
static final int HBLKSIZE = 4096;
|
||||
|
||||
class SizeKind implements Comparable<SizeKind>
|
||||
{
|
||||
int size;
|
||||
int kind;
|
||||
|
||||
public SizeKind(int size, int kind)
|
||||
{
|
||||
this.size = size;
|
||||
this.kind = kind;
|
||||
}
|
||||
|
||||
public int compareTo(SizeKind b)
|
||||
{
|
||||
if (this.size != b.size)
|
||||
return this.size - b.size;
|
||||
return this.kind - b.kind;
|
||||
}
|
||||
}
|
||||
|
||||
class PtrMarks
|
||||
{
|
||||
long ptr;
|
||||
int marks;
|
||||
|
||||
public PtrMarks(long ptr, int marks)
|
||||
{
|
||||
this.ptr = ptr;
|
||||
this.marks = marks;
|
||||
}
|
||||
}
|
||||
|
||||
private TreeMap<SizeKind, ArrayList<PtrMarks>> map =
|
||||
new TreeMap<SizeKind, ArrayList<PtrMarks>>();
|
||||
|
||||
public BlockMap(BufferedReader reader) throws IOException
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
String s = reader.readLine();
|
||||
if (s == null)
|
||||
break;
|
||||
if (s.charAt(0) == '#')
|
||||
continue;
|
||||
if (s.indexOf("Begin block map") >= 0)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
s = reader.readLine();
|
||||
if (s.charAt(0) == '#')
|
||||
continue;
|
||||
if (s.indexOf("End block map") >= 0)
|
||||
return;
|
||||
String[] items = s.split(",");
|
||||
long ptr = 0;
|
||||
int kind = 0, size = 0, marks = 0;
|
||||
for (int i=0; i<items.length; i++)
|
||||
{
|
||||
String[] x = items[i].split(" ");
|
||||
String last = x[x.length - 1];
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
ptr = MemoryMap.parseHexLong(last.substring(2));
|
||||
break;
|
||||
case 1:
|
||||
kind = Integer.parseInt(last);
|
||||
break;
|
||||
case 2:
|
||||
size = Integer.parseInt(last);
|
||||
break;
|
||||
case 3:
|
||||
marks = Integer.parseInt(last);
|
||||
break;
|
||||
}
|
||||
}
|
||||
SizeKind sk = new SizeKind(size, kind);
|
||||
ArrayList<PtrMarks> m = map.get(sk);
|
||||
if (m == null)
|
||||
{
|
||||
m = new ArrayList<PtrMarks>();
|
||||
map.put(sk, m);
|
||||
}
|
||||
PtrMarks pm = new PtrMarks(ptr, marks);
|
||||
m.add(pm);
|
||||
} // inner loop
|
||||
} // started inner loop
|
||||
} // outer loop - finding begin
|
||||
} // memoryMap
|
||||
|
||||
public void dump()
|
||||
{
|
||||
System.out.println();
|
||||
System.out.println();
|
||||
System.out.println("*** Used Blocks ***\n");
|
||||
System.out.println();
|
||||
System.out.println(" Size Kind Blocks Used Free Wasted");
|
||||
System.out.println("------- ------------- ------- ---------- ---------- -------");
|
||||
|
||||
int total_blocks = 0, total_used = 0, total_free = 0, total_wasted = 0;
|
||||
|
||||
for (Map.Entry<SizeKind, ArrayList<PtrMarks>> me : map.entrySet())
|
||||
{
|
||||
SizeKind sk = me.getKey();
|
||||
|
||||
System.out.println(MemoryAnalyze.format(sk.size, 7) + " "
|
||||
+ MemoryAnalyze.kindToName(sk.kind));
|
||||
|
||||
int sub_blocks = 0, sub_used = 0, sub_free = 0, sub_wasted = 0;
|
||||
int sub_count = 0;
|
||||
|
||||
ArrayList<PtrMarks> v = me.getValue();
|
||||
|
||||
for (PtrMarks pm : v)
|
||||
{
|
||||
int bytes = sk.size;
|
||||
int blocks = (sk.size + HBLKSIZE - 1) / HBLKSIZE;
|
||||
int used;
|
||||
int free;
|
||||
int wasted;
|
||||
|
||||
if (bytes < HBLKSIZE)
|
||||
{
|
||||
used = bytes * pm.marks;
|
||||
free = bytes * (HBLKSIZE / bytes - pm.marks);
|
||||
wasted = HBLKSIZE - HBLKSIZE / bytes * bytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pm.marks != 0)
|
||||
{
|
||||
used = bytes;
|
||||
free = 0;
|
||||
wasted = (bytes + HBLKSIZE - 1)
|
||||
/ HBLKSIZE * HBLKSIZE - used;
|
||||
}
|
||||
else
|
||||
{
|
||||
used = 0;
|
||||
free = bytes;
|
||||
wasted = 0;
|
||||
}
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(" ");
|
||||
sb.append(MemoryAnalyze.format(blocks, 5));
|
||||
sb.append(" ");
|
||||
sb.append(MemoryAnalyze.format(used, 9));
|
||||
sb.append(" ");
|
||||
sb.append(MemoryAnalyze.format(free, 9));
|
||||
sb.append(" ");
|
||||
sb.append(MemoryAnalyze.format(wasted, 9));
|
||||
System.out.println(sb);
|
||||
|
||||
sub_blocks += blocks;
|
||||
sub_used += used;
|
||||
sub_free += free;
|
||||
sub_wasted += wasted;
|
||||
sub_count++;
|
||||
|
||||
total_blocks += blocks;
|
||||
total_used += used;
|
||||
total_free += free;
|
||||
total_wasted += wasted;
|
||||
} // blocks with size/kind
|
||||
if (sub_count > 1)
|
||||
{
|
||||
System.out.println(
|
||||
" ------- ---------- ---------- -------");
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(" ");
|
||||
sb.append(MemoryAnalyze.format(sub_blocks, 5));
|
||||
sb.append(" ");
|
||||
sb.append(MemoryAnalyze.format(sub_used, 9));
|
||||
sb.append(" ");
|
||||
sb.append(MemoryAnalyze.format(sub_free, 9));
|
||||
sb.append(" ");
|
||||
sb.append(MemoryAnalyze.format(sub_wasted, 9));
|
||||
System.out.println(sb);
|
||||
}
|
||||
} // size/kind
|
||||
|
||||
System.out.println("------- ------------- ------- ---------- ---------- -------");
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(" ");
|
||||
sb.append(MemoryAnalyze.format(total_blocks, 5));
|
||||
sb.append(" ");
|
||||
sb.append(MemoryAnalyze.format(total_used, 9));
|
||||
sb.append(" ");
|
||||
sb.append(MemoryAnalyze.format(total_free, 9));
|
||||
sb.append(" ");
|
||||
sb.append(MemoryAnalyze.format(total_wasted, 9));
|
||||
System.out.println(sb);
|
||||
System.out.println("Total bytes = "
|
||||
+ MemoryAnalyze.format(total_blocks * HBLKSIZE, 10));
|
||||
}
|
||||
}
|
115
libjava/gnu/gcj/tools/gc_analyze/BytePtr.java
Normal file
115
libjava/gnu/gcj/tools/gc_analyze/BytePtr.java
Normal file
|
@ -0,0 +1,115 @@
|
|||
/* BytePtr.java -- Container for bytes from a memory image.
|
||||
Copyright (C) 2007 Free Software Foundation
|
||||
|
||||
This file is part of libgcj.
|
||||
|
||||
This software is copyrighted work licensed under the terms of the
|
||||
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
|
||||
details. */
|
||||
|
||||
package gnu.gcj.tools.gc_analyze;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class BytePtr
|
||||
{
|
||||
ByteBuffer content;
|
||||
int wordSize;
|
||||
|
||||
BytePtr(ByteBuffer b, int ws)
|
||||
{
|
||||
content = b;
|
||||
wordSize = ws;
|
||||
}
|
||||
|
||||
public int getsize()
|
||||
{
|
||||
return content.limit();
|
||||
}
|
||||
|
||||
public int getByte(int offset)
|
||||
{
|
||||
return content.get(offset);
|
||||
}
|
||||
|
||||
public int getInt(int n)
|
||||
{
|
||||
return content.getInt(n * 4);
|
||||
}
|
||||
|
||||
public int getShort(int n)
|
||||
{
|
||||
return content.getShort(n * 2);
|
||||
}
|
||||
|
||||
public long getWord(int n)
|
||||
{
|
||||
if (4 == wordSize)
|
||||
return 0xffffffffL & content.getInt(n * 4);
|
||||
else
|
||||
return content.getLong(n * 8);
|
||||
}
|
||||
|
||||
public int intsPerWord()
|
||||
{
|
||||
return (4 == wordSize) ? 1 : 2;
|
||||
}
|
||||
|
||||
public BytePtr getRegion(int offset, int size)
|
||||
{
|
||||
int oldLimit = content.limit();
|
||||
content.position(offset);
|
||||
content.limit(offset + size);
|
||||
ByteBuffer n = content.slice();
|
||||
content.position(0);
|
||||
content.limit(oldLimit);
|
||||
|
||||
return new BytePtr(n, wordSize);
|
||||
}
|
||||
|
||||
public void setInt(int a, int n)
|
||||
{
|
||||
content.putInt(a * 4, n);
|
||||
}
|
||||
|
||||
public void dump()
|
||||
{
|
||||
// 38 5a f4 2a 50 bd 04 10 10 00 00 00 0e 00 00 00 8Z.*P...........
|
||||
int i;
|
||||
StringBuilder b = new StringBuilder(67);
|
||||
for (i = 0; i < 66; i++)
|
||||
b.append(' ');
|
||||
b.append('\n');
|
||||
|
||||
i = 0;
|
||||
do
|
||||
{
|
||||
for (int j = 0; j < 16; j++)
|
||||
{
|
||||
int k = i + j;
|
||||
|
||||
if (k < content.limit())
|
||||
{
|
||||
int v = 0xff & getByte(k);
|
||||
// hex
|
||||
int v1 = v/16;
|
||||
b.setCharAt(j * 3 + 0,
|
||||
(char)(v1 >= 10 ? 'a' - 10 + v1 : v1 + '0'));
|
||||
v1 = v % 16;
|
||||
b.setCharAt(j * 3 + 1,
|
||||
(char)(v1 >= 10 ? 'a' - 10 + v1 : v1 + '0'));
|
||||
// ascii
|
||||
b.setCharAt(j + 50, (char)((v >= 32 && v <= 127) ? v: '.'));
|
||||
}
|
||||
else
|
||||
{
|
||||
b.setCharAt(j * 3 + 0, ' ');
|
||||
b.setCharAt(j * 3 + 1, ' ');
|
||||
b.setCharAt(j + 50, ' ');
|
||||
}
|
||||
}
|
||||
i += 16;
|
||||
System.out.print(b);
|
||||
} while (i < content.limit());
|
||||
}
|
||||
}
|
72
libjava/gnu/gcj/tools/gc_analyze/ItemList.java
Normal file
72
libjava/gnu/gcj/tools/gc_analyze/ItemList.java
Normal file
|
@ -0,0 +1,72 @@
|
|||
/* ItemList.java -- Maps all objects keyed by their addresses.
|
||||
Copyright (C) 2007 Free Software Foundation
|
||||
|
||||
This file is part of libgcj.
|
||||
|
||||
This software is copyrighted work licensed under the terms of the
|
||||
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
|
||||
details. */
|
||||
|
||||
package gnu.gcj.tools.gc_analyze;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
class ItemList
|
||||
{
|
||||
public ItemList()
|
||||
{
|
||||
}
|
||||
|
||||
private TreeMap<Long, HashMap<ObjectMap.ObjectItem, Integer>> map;
|
||||
|
||||
public void add(ObjectMap.ObjectItem item)
|
||||
{
|
||||
if (map == null)
|
||||
map = new TreeMap<Long, HashMap<ObjectMap.ObjectItem, Integer>>();
|
||||
Long x = new Long(item.klass);
|
||||
HashMap<ObjectMap.ObjectItem, Integer> list = map.get(x);
|
||||
if (list == null)
|
||||
{
|
||||
list = new HashMap<ObjectMap.ObjectItem, Integer>();
|
||||
map.put(x, list);
|
||||
}
|
||||
Integer count = list.get(item);
|
||||
if (count == null)
|
||||
list.put(item, new Integer(1));
|
||||
else
|
||||
list.put(item, new Integer(count.intValue() + 1));
|
||||
}
|
||||
|
||||
void dump(String title, SymbolLookup lookup) throws IOException
|
||||
{
|
||||
if (map == null)
|
||||
return;
|
||||
System.out.println(title);
|
||||
for (Map.Entry<Long, HashMap<ObjectMap.ObjectItem, Integer>> me :
|
||||
map.entrySet())
|
||||
{
|
||||
HashMap<ObjectMap.ObjectItem, Integer> list = me.getValue();
|
||||
boolean first = true;
|
||||
|
||||
for (Map.Entry<ObjectMap.ObjectItem, Integer> me2 : list.entrySet())
|
||||
{
|
||||
ObjectMap.ObjectItem item = me2.getKey();
|
||||
Integer count = me2.getValue();
|
||||
if (first)
|
||||
{
|
||||
String name =
|
||||
MemoryAnalyze.getSymbolPretty(lookup, item, false);
|
||||
System.out.println(" " + name + ":");
|
||||
first = false;
|
||||
}
|
||||
System.out.print(" 0x" + Long.toHexString(item.ptr));
|
||||
if (count.intValue() != 1)
|
||||
System.out.print(" * " + count);
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
458
libjava/gnu/gcj/tools/gc_analyze/MemoryAnalyze.java
Normal file
458
libjava/gnu/gcj/tools/gc_analyze/MemoryAnalyze.java
Normal file
|
@ -0,0 +1,458 @@
|
|||
/* MemoryAnalyze.java -- Analyzes a libgcj heap dump.
|
||||
Copyright (C) 2007 Free Software Foundation
|
||||
|
||||
This file is part of libgcj.
|
||||
|
||||
This software is copyrighted work licensed under the terms of the
|
||||
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
|
||||
details. */
|
||||
|
||||
package gnu.gcj.tools.gc_analyze;
|
||||
|
||||
import gnu.classpath.tools.getopt.FileArgumentCallback;
|
||||
import gnu.classpath.tools.getopt.Option;
|
||||
import gnu.classpath.tools.getopt.OptionException;
|
||||
import gnu.classpath.tools.getopt.Parser;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
class MemoryAnalyze
|
||||
{
|
||||
public MemoryAnalyze()
|
||||
{
|
||||
}
|
||||
|
||||
private static NumberFormat numberFormat;
|
||||
private static boolean verbose;
|
||||
static String format(long number, int digits)
|
||||
{
|
||||
if (numberFormat == null)
|
||||
{
|
||||
numberFormat = NumberFormat.getNumberInstance();
|
||||
numberFormat.setGroupingUsed(true);
|
||||
}
|
||||
String temp = numberFormat.format(number);
|
||||
int spaces = digits - temp.length();
|
||||
if (spaces < 0)
|
||||
spaces = 0;
|
||||
return " ".substring(0,spaces) + temp;
|
||||
}
|
||||
|
||||
static void sorted_report(String description,
|
||||
int total_space,
|
||||
ArrayList<String> list,
|
||||
Comparator<String> comparator)
|
||||
{
|
||||
System.out.println("*** " + description + " ***");
|
||||
System.out.println();
|
||||
System.out.println(" Total Size Count Size Description");
|
||||
System.out.println("-------------- ----- -------- -----------------------------------");
|
||||
Collections.sort(list, comparator);
|
||||
for (Iterator it = list.iterator(); it.hasNext(); )
|
||||
{
|
||||
String v = (String)it.next();
|
||||
System.out.println(stripend(v));
|
||||
}
|
||||
System.out.println("-------------- ----- -------- -----------------------------------");
|
||||
System.out.println(format(total_space, 14));
|
||||
System.out.println();
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
private static String stripend(String s)
|
||||
{
|
||||
int n = s.lastIndexOf(" /");
|
||||
if (n > 0)
|
||||
return s.substring(0,n);
|
||||
return s;
|
||||
}
|
||||
|
||||
static class SubstringComparator implements Comparator<String>
|
||||
{
|
||||
private int begin, end;
|
||||
private boolean reverse;
|
||||
|
||||
SubstringComparator(int begin, int end, boolean reverse)
|
||||
{
|
||||
this.begin = begin;
|
||||
this.end = end;
|
||||
this.reverse = reverse;
|
||||
}
|
||||
|
||||
public int compare(String s1, String s2)
|
||||
{
|
||||
if (end == 0)
|
||||
s1 = s1.substring(begin);
|
||||
else
|
||||
s1 = s1.substring(begin, end);
|
||||
|
||||
if (end == 0)
|
||||
s2 = s2.substring(begin);
|
||||
else
|
||||
s2 = s2.substring(begin, end);
|
||||
int i = s1.compareTo(s2);
|
||||
if (reverse)
|
||||
return -i;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
static class OptionParser extends Parser
|
||||
{
|
||||
int filesFound;
|
||||
|
||||
OptionParser()
|
||||
{
|
||||
super("gc-analyze",
|
||||
"gc-analyze (" + System.getProperty("java.vm.version") + ")");
|
||||
|
||||
add(new Option('d',
|
||||
"Directory containing runtime objects",
|
||||
"directory")
|
||||
{
|
||||
public void parsed(String argument) throws OptionException
|
||||
{
|
||||
ToolPrefix.pathPrefix = argument;
|
||||
}
|
||||
});
|
||||
|
||||
add(new Option('p',
|
||||
"Binary tool prefix, prepended to nm and readelf to "
|
||||
+ "obtain target specific versions of these commands",
|
||||
"prefix")
|
||||
{
|
||||
public void parsed(String argument) throws OptionException
|
||||
{
|
||||
ToolPrefix.toolPrefix = argument;
|
||||
}
|
||||
});
|
||||
|
||||
add(new Option("verbose", 'v',
|
||||
"Verbose output; requires filename.bytes")
|
||||
{
|
||||
public void parsed(String argument) throws OptionException
|
||||
{
|
||||
verbose = true;
|
||||
}
|
||||
});
|
||||
|
||||
setHeader("usage: gc-analyze [-v] [-p tool-prefix] [-d <directory>] "
|
||||
+ "filename");
|
||||
}
|
||||
|
||||
protected void validate() throws OptionException
|
||||
{
|
||||
if (filesFound != 1)
|
||||
throw new OptionException("Must specify exactly one filename");
|
||||
}
|
||||
|
||||
public String[] parse(String[] inArgs)
|
||||
{
|
||||
final ArrayList<String> fileResult = new ArrayList<String>();
|
||||
parse(inArgs, new FileArgumentCallback()
|
||||
{
|
||||
public void notifyFile(String fileArgument)
|
||||
{
|
||||
filesFound++;
|
||||
fileResult.add(fileArgument);
|
||||
}
|
||||
});
|
||||
return fileResult.toArray(new String[1]);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
class Info
|
||||
{
|
||||
int size;
|
||||
int count;
|
||||
}
|
||||
int total_space = 0;
|
||||
|
||||
Parser optionParser = new OptionParser();
|
||||
|
||||
String rest[] = optionParser.parse(args);
|
||||
|
||||
String filename = rest[0];
|
||||
|
||||
try
|
||||
{
|
||||
BufferedReader reader =
|
||||
new BufferedReader(new InputStreamReader(new FileInputStream(filename)));
|
||||
SymbolLookup lookup = new SymbolLookup(reader, filename + ".bytes");
|
||||
ObjectMap objectMap = new ObjectMap(reader);
|
||||
BlockMap blockMap = new BlockMap(reader);
|
||||
reader.close();
|
||||
|
||||
// add info to item(s)
|
||||
// add item.klass
|
||||
for (Map.Entry<Long, ObjectMap.ObjectItem> me : objectMap)
|
||||
{
|
||||
ObjectMap.ObjectItem item = me.getValue();
|
||||
|
||||
// try to get a klass (happens with intern'ed strings...)
|
||||
if (item.klass==0)
|
||||
{
|
||||
BytePtr p = lookup.getBytePtr(item.ptr, item.size);
|
||||
if (p!=null)
|
||||
{
|
||||
long vtable = p.getWord(0);
|
||||
String sym =
|
||||
lookup.getSymbolViaVtable(vtable - 2 * lookup.memoryMap.wordSize);
|
||||
if (sym != null)
|
||||
{
|
||||
item.typeName = SymbolTable.demangleVTName(sym);
|
||||
}
|
||||
else if (vtable != 0)
|
||||
{
|
||||
// get klass from vtable
|
||||
p = lookup.getBytePtr(vtable,
|
||||
lookup.memoryMap.wordSize);
|
||||
if (p != null)
|
||||
{
|
||||
long klass = p.getWord(0);
|
||||
item.klass = klass;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// figure out strings
|
||||
String class_name;
|
||||
if (null == item.typeName)
|
||||
{
|
||||
class_name =
|
||||
MemoryAnalyze.getSymbolPretty(lookup, item, false);
|
||||
item.typeName = class_name;
|
||||
}
|
||||
else
|
||||
{
|
||||
class_name = item.typeName;
|
||||
}
|
||||
System.out.print("class_name=[" + class_name + "]");
|
||||
|
||||
if (class_name.compareTo("_ZTVN4java4lang6StringE")==0
|
||||
|| class_name.compareTo("java.lang.String")==0)
|
||||
{
|
||||
BytePtr p = lookup.getBytePtr(item.ptr, item.size);
|
||||
long data = p.getWord(1);
|
||||
int boffset = p.getInt(2 * p.intsPerWord());
|
||||
int count = p.getInt(1 + 2 * p.intsPerWord());
|
||||
int hash = p.getInt(2 + 2 * p.intsPerWord());
|
||||
BytePtr chars = lookup.getBytePtr(data+boffset, count * 2);
|
||||
StringBuffer sb = new StringBuffer(count);
|
||||
for (int qq = 0; qq<count; qq++)
|
||||
sb.append((char)chars.getShort(qq));
|
||||
int newhash = sb.toString().hashCode();
|
||||
if (newhash!=hash)
|
||||
{
|
||||
p.setInt(4, newhash);
|
||||
}
|
||||
|
||||
item.string = sb.toString();
|
||||
System.out.println(" value = \"" + item.string + "\"");
|
||||
if (data != item.ptr)
|
||||
{
|
||||
ObjectMap.ObjectItem next = objectMap.get(data);
|
||||
if (next != null)
|
||||
next.stringData = true;
|
||||
else
|
||||
System.out.println("String [" + item.string + "] at "
|
||||
+ Long.toHexString(item.ptr)
|
||||
+ " can't find array at "
|
||||
+ Long.toHexString(data));
|
||||
}
|
||||
}
|
||||
else if (null != item.string)
|
||||
System.out.println(" value = \"" + item.string + "\"");
|
||||
else
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
|
||||
HashMap<String, Info> map = new HashMap<String, Info>();
|
||||
for (Map.Entry<Long, ObjectMap.ObjectItem> me : objectMap)
|
||||
{
|
||||
ObjectMap.ObjectItem item = me.getValue();
|
||||
String name = getSymbolPretty(lookup, item, true);
|
||||
Info info = map.get(name);
|
||||
if (info == null)
|
||||
{
|
||||
info = new Info();
|
||||
info.count = 0;
|
||||
info.size = item.size;
|
||||
map.put(name, info);
|
||||
}
|
||||
info.count++;
|
||||
total_space += item.size;
|
||||
}
|
||||
|
||||
ArrayList<String> list = new ArrayList<String>();
|
||||
for (Iterator it = map.entrySet().iterator(); it.hasNext(); )
|
||||
{
|
||||
Map.Entry me = (Map.Entry)it.next();
|
||||
String name = (String)me.getKey();
|
||||
Info info = (Info)me.getValue();
|
||||
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append(format(info.count * info.size * 100 / total_space,
|
||||
3));
|
||||
sb.append("%");
|
||||
sb.append(format(info.count * info.size, 10));
|
||||
sb.append(" = ");
|
||||
sb.append(format(info.count, 7));
|
||||
sb.append(" * ");
|
||||
sb.append(format(info.size, 9));
|
||||
sb.append(" - ");
|
||||
sb.append(name);
|
||||
list.add(sb.toString());
|
||||
}
|
||||
|
||||
sorted_report("Memory Usage Sorted by Total Size",
|
||||
total_space, list, new SubstringComparator(5,14,true));
|
||||
sorted_report("Memory Usage Sorted by Description",
|
||||
total_space, list, new SubstringComparator(39,0,false));
|
||||
sorted_report("Memory Usage Sorted by Count",
|
||||
total_space, list, new SubstringComparator(17,25,true));
|
||||
sorted_report("Memory Usage Sorted by Size",
|
||||
total_space, list, new SubstringComparator(28,37,true));
|
||||
|
||||
blockMap.dump();
|
||||
|
||||
// dump raw memory
|
||||
if (verbose)
|
||||
{
|
||||
// analyze references
|
||||
for (Map.Entry<Long, ObjectMap.ObjectItem> me : objectMap)
|
||||
{
|
||||
long ptr = me.getKey();
|
||||
ObjectMap.ObjectItem item = me.getValue();
|
||||
BytePtr p = lookup.getBytePtr(ptr, item.size);
|
||||
if (p == null)
|
||||
System.out.println("can't find ptr 0x"
|
||||
+ Long.toHexString(ptr));
|
||||
else if (item.kind != 0) // not GC_PTRFREE
|
||||
for (int i = 1;
|
||||
i < item.size / lookup.memoryMap.wordSize; i++)
|
||||
{
|
||||
long maybe_ptr = p.getWord(i);
|
||||
ObjectMap.ObjectItem item2 = objectMap.get(maybe_ptr);
|
||||
if (item2 != null)
|
||||
{
|
||||
item2.pointed_by.add(item);
|
||||
item.points_to.add(item2);
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println();
|
||||
System.out.println("*** All Objects ***");
|
||||
System.out.println();
|
||||
|
||||
for (Map.Entry<Long, ObjectMap.ObjectItem> me : objectMap)
|
||||
{
|
||||
long ptr = me.getKey();
|
||||
ObjectMap.ObjectItem item = me.getValue();
|
||||
String name = getSymbolPretty(lookup, item, false);
|
||||
System.out.print("0x" + Long.toHexString(ptr) + " - " + name
|
||||
+ " (" + item.size + ")");
|
||||
if (item.string != null)
|
||||
System.out.println(" \"" + item.string + "\"");
|
||||
else
|
||||
System.out.println();
|
||||
|
||||
BytePtr p = lookup.getBytePtr(ptr, item.size);
|
||||
|
||||
if (p == null)
|
||||
System.out.println(
|
||||
"can't find memory; recently allocated from free list?");
|
||||
else
|
||||
p.dump();
|
||||
|
||||
item.points_to.dump(" points to:", lookup);
|
||||
item.pointed_by.dump(" pointed to by:", lookup);
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static String kindToName(int kind)
|
||||
{
|
||||
String name;
|
||||
switch (kind)
|
||||
{
|
||||
case 0:
|
||||
name = "GC_PTRFREE";
|
||||
break;
|
||||
case 1:
|
||||
name = "GC_NORMAL";
|
||||
break;
|
||||
case 2:
|
||||
name = "GC_UNCOLLECTABLE";
|
||||
break;
|
||||
case 3:
|
||||
name = "GC_AUUNCOLLCTABLE";
|
||||
break;
|
||||
case 4:
|
||||
name = "(Java)";
|
||||
break;
|
||||
case 5:
|
||||
name = "(Java Debug)";
|
||||
break;
|
||||
case 6:
|
||||
name = "(Java Array)";
|
||||
break;
|
||||
default:
|
||||
name = "(Kind " + kind + ")";
|
||||
break;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
public static String getSymbolPretty(SymbolLookup lookup,
|
||||
ObjectMap.ObjectItem item,
|
||||
boolean bsize)
|
||||
throws IOException
|
||||
{
|
||||
|
||||
String name = item.typeName;
|
||||
|
||||
if (name == null)
|
||||
name = lookup.getSymbol(item.klass);
|
||||
|
||||
if (name == null)
|
||||
{
|
||||
String v = lookup.decodeUTF8(item.ptr, item.size);
|
||||
if (null != v)
|
||||
{
|
||||
name = "UTF8Const";
|
||||
item.string = v;
|
||||
}
|
||||
}
|
||||
|
||||
if (name == null)
|
||||
{
|
||||
name = kindToName(item.kind);
|
||||
}
|
||||
if (item.kind==6)
|
||||
name += "[" + format(item.data, 0) + "]";
|
||||
if (bsize)
|
||||
name = name + " / " + format(item.size, 7);
|
||||
return name;
|
||||
}
|
||||
}
|
359
libjava/gnu/gcj/tools/gc_analyze/MemoryMap.java
Normal file
359
libjava/gnu/gcj/tools/gc_analyze/MemoryMap.java
Normal file
|
@ -0,0 +1,359 @@
|
|||
/* MemoryMap.java -- Maps address ranges to their data.
|
||||
Copyright (C) 2007 Free Software Foundation
|
||||
|
||||
This file is part of libgcj.
|
||||
|
||||
This software is copyrighted work licensed under the terms of the
|
||||
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
|
||||
details. */
|
||||
|
||||
package gnu.gcj.tools.gc_analyze;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.EOFException;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
|
||||
/**
|
||||
* Reads /proc/self/maps output from dump file.
|
||||
* Creates map of <filename> to Range.
|
||||
*
|
||||
* Returns filename given address.
|
||||
* Returns offset given address.
|
||||
* Returns BytePtr given address.
|
||||
*
|
||||
*/
|
||||
class MemoryMap
|
||||
{
|
||||
static class RangeComparator implements Comparator<Range>
|
||||
{
|
||||
public int compare(Range r1, Range r2)
|
||||
{
|
||||
if (r2.end == 0 && r1.end != 0)
|
||||
return -compare(r2, r1);
|
||||
|
||||
if (r1.begin < r2.begin)
|
||||
return -1;
|
||||
else if (r1.begin >= r2.end)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static class Range
|
||||
{
|
||||
long begin;
|
||||
long end;
|
||||
|
||||
long offset;
|
||||
String filename;
|
||||
Range()
|
||||
{
|
||||
}
|
||||
|
||||
Range(long b, long e, String s, long o)
|
||||
{
|
||||
begin = b;
|
||||
end = e;
|
||||
filename = s;
|
||||
offset = o;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the string as an unsigned hexadecimal number. This is
|
||||
* similar to Long.parseInt(s,16), but without the restriction that
|
||||
* values that have the sign bit set not being allowed.
|
||||
*
|
||||
* @param s the number as a String.
|
||||
* @return the number.
|
||||
*/
|
||||
static long parseHexLong(String s)
|
||||
{
|
||||
if (s.length() > 16)
|
||||
throw new NumberFormatException();
|
||||
long r = 0;
|
||||
for (int i = 0; i < s.length(); i++)
|
||||
{
|
||||
int digit = 0;
|
||||
char c = s.charAt(i);
|
||||
switch (c)
|
||||
{
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
digit = c - '0';
|
||||
break;
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f':
|
||||
digit = 10 + c - 'a';
|
||||
break;
|
||||
case 'A':
|
||||
case 'B':
|
||||
case 'C':
|
||||
case 'D':
|
||||
case 'E':
|
||||
case 'F':
|
||||
digit = 10 + c - 'A';
|
||||
break;
|
||||
default:
|
||||
throw new NumberFormatException();
|
||||
}
|
||||
r = (r << 4) + digit;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
// String filename -> Range
|
||||
TreeSet<Range> map = new TreeSet<Range>(new RangeComparator());
|
||||
HashMap<String, SymbolTable> symbolTables =
|
||||
new HashMap<String, SymbolTable>();
|
||||
ByteOrder byteOrder;
|
||||
int wordSize;
|
||||
|
||||
public MemoryMap(BufferedReader reader,
|
||||
String rawFileName) throws IOException
|
||||
{
|
||||
FileChannel raw = (new RandomAccessFile(rawFileName, "r")).getChannel();
|
||||
ByteBuffer buf = ByteBuffer.allocate(8);
|
||||
raw.read(buf);
|
||||
if (buf.hasRemaining())
|
||||
{
|
||||
raw.close();
|
||||
throw new EOFException();
|
||||
}
|
||||
buf.flip();
|
||||
wordSize = buf.get();
|
||||
|
||||
if (wordSize == 8 || wordSize == 4)
|
||||
byteOrder = ByteOrder.LITTLE_ENDIAN;
|
||||
else
|
||||
{
|
||||
byteOrder = ByteOrder.BIG_ENDIAN;
|
||||
buf.rewind();
|
||||
wordSize = buf.getInt();
|
||||
if (0 == wordSize)
|
||||
wordSize = buf.getInt();
|
||||
}
|
||||
switch (wordSize)
|
||||
{
|
||||
case 4:
|
||||
case 8:
|
||||
break;
|
||||
default:
|
||||
throw new IOException("Bad .bytes file header");
|
||||
}
|
||||
buf = ByteBuffer.allocate(3 * wordSize);
|
||||
buf.order(byteOrder);
|
||||
raw.position(0L);
|
||||
|
||||
for(;;)
|
||||
{
|
||||
// Read the block header.
|
||||
buf.clear();
|
||||
if (-1 == raw.read(buf))
|
||||
{
|
||||
//EOF
|
||||
raw.close();
|
||||
break;
|
||||
}
|
||||
if (buf.hasRemaining())
|
||||
{
|
||||
raw.close();
|
||||
throw new EOFException();
|
||||
}
|
||||
buf.flip();
|
||||
long dummy
|
||||
= (wordSize == 4) ? (buf.getInt() & 0xffffffffL) : buf.getLong();
|
||||
if (dummy != wordSize)
|
||||
throw new IOException("Bad .bytes file header");
|
||||
long start
|
||||
= wordSize == 4 ? (buf.getInt() & 0xffffffffL) : buf.getLong();
|
||||
long length
|
||||
= wordSize == 4 ? (buf.getInt() & 0xffffffffL) : buf.getLong();
|
||||
if (length < 0L)
|
||||
throw new IOException("Bad .bytes file header");
|
||||
|
||||
long currentPos = raw.position();
|
||||
raw.position(currentPos + length);
|
||||
|
||||
Range range = new Range(start, start + length,
|
||||
rawFileName, currentPos);
|
||||
map.add(range);
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
String s = reader.readLine();
|
||||
if (s == null)
|
||||
break;
|
||||
if (s.indexOf("Begin address map") >= 0)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
s = reader.readLine();
|
||||
if (s.indexOf("End address map") >= 0)
|
||||
{
|
||||
dump();
|
||||
return;
|
||||
}
|
||||
int endOfAddress = s.indexOf('-');
|
||||
long address = parseHexLong(s.substring(0, endOfAddress));
|
||||
int endOfAddress2 = s.indexOf(' ', endOfAddress + 1);
|
||||
long address2 = parseHexLong(s.substring(endOfAddress + 1,
|
||||
endOfAddress2));
|
||||
int endOfOffset = s.indexOf(' ', endOfAddress2 + 6);
|
||||
long offset;
|
||||
try
|
||||
{
|
||||
offset = parseHexLong(s.substring(endOfAddress2 + 6,
|
||||
endOfOffset));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
offset = 0;
|
||||
}
|
||||
int end = s.indexOf('/');
|
||||
|
||||
if (end > 0)
|
||||
{
|
||||
String file = s.substring(end);
|
||||
if (file.startsWith("/dev/"))
|
||||
continue;
|
||||
|
||||
Range r = new Range(address, address2, file, offset);
|
||||
if (offset == 0)
|
||||
{
|
||||
// Read the file's symbol table
|
||||
try
|
||||
{
|
||||
File f = ToolPrefix.fileForName(file);
|
||||
if (f != null)
|
||||
{
|
||||
SymbolTable st = new SymbolTable(f.getPath());
|
||||
if (st.loadAddr != address)
|
||||
st.relocation = address - st.loadAddr;
|
||||
symbolTables.put(file, st);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
map.add(r);
|
||||
}
|
||||
} // inner loop
|
||||
} // started inner loop
|
||||
} // outer loop - finding begin
|
||||
} // memoryMap
|
||||
|
||||
|
||||
public void dump()
|
||||
{
|
||||
System.out.println("MemoryMap:");
|
||||
for (Range r : map)
|
||||
{
|
||||
System.out.println(Long.toHexString(r.begin) + "-"
|
||||
+ Long.toHexString(r.end) + " -> "
|
||||
+ r.filename + " offset "
|
||||
+ Long.toHexString(r.offset));
|
||||
}
|
||||
}
|
||||
|
||||
Range getRange(long addr)
|
||||
{
|
||||
Range r = new Range();
|
||||
r.begin = addr;
|
||||
SortedSet<Range> t = map.tailSet(r);
|
||||
if (t.isEmpty())
|
||||
return null;
|
||||
Range c = t.first();
|
||||
if (c.begin <= addr && addr < c.end)
|
||||
return c;
|
||||
return null;
|
||||
}
|
||||
|
||||
String getFile(long addr)
|
||||
{
|
||||
Range r = getRange(addr);
|
||||
if (null != r)
|
||||
return r.filename;
|
||||
return null;
|
||||
}
|
||||
|
||||
long getOffset(long addr)
|
||||
{
|
||||
Range r = getRange(addr);
|
||||
if (null != r)
|
||||
return r.offset;
|
||||
return 0L;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BytePtr which includes given address.
|
||||
*/
|
||||
BytePtr getBytePtr(long addr, int length) throws IOException
|
||||
{
|
||||
Range r = getRange(addr);
|
||||
|
||||
if (null == r)
|
||||
return null;
|
||||
|
||||
File f = ToolPrefix.fileForName(r.filename);
|
||||
if (null == f)
|
||||
return null;
|
||||
|
||||
if (addr + length > r.end)
|
||||
length = (int)(r.end - addr);
|
||||
|
||||
ByteBuffer b = ByteBuffer.allocate(length);
|
||||
b.order(byteOrder);
|
||||
|
||||
FileChannel fc = (new RandomAccessFile(f, "r")).getChannel();
|
||||
fc.position(r.offset + addr - r.begin);
|
||||
int nr = fc.read(b);
|
||||
fc.close();
|
||||
if (nr != length)
|
||||
return null;
|
||||
b.flip();
|
||||
return new BytePtr(b, wordSize);
|
||||
}
|
||||
|
||||
public String getSymbol(long addr)
|
||||
{
|
||||
Range r = getRange(addr);
|
||||
|
||||
if (r == null)
|
||||
return null;
|
||||
|
||||
SymbolTable st = symbolTables.get(r.filename);
|
||||
if (st == null)
|
||||
return null;
|
||||
|
||||
// Apply relocation
|
||||
addr -= st.relocation;
|
||||
|
||||
return st.getSymbol(addr);
|
||||
}
|
||||
}
|
140
libjava/gnu/gcj/tools/gc_analyze/ObjectMap.java
Normal file
140
libjava/gnu/gcj/tools/gc_analyze/ObjectMap.java
Normal file
|
@ -0,0 +1,140 @@
|
|||
/* ObjectMap.java -- Contains a map of all objects keyed by their addresses.
|
||||
Copyright (C) 2007 Free Software Foundation
|
||||
|
||||
This file is part of libgcj.
|
||||
|
||||
This software is copyrighted work licensed under the terms of the
|
||||
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
|
||||
details. */
|
||||
|
||||
package gnu.gcj.tools.gc_analyze;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
class ObjectMap implements Iterable<Map.Entry<Long, ObjectMap.ObjectItem>>
|
||||
{
|
||||
|
||||
class ObjectItem
|
||||
{
|
||||
int used;
|
||||
int size;
|
||||
int kind;
|
||||
long klass;
|
||||
long data;
|
||||
long ptr;
|
||||
String typeName;
|
||||
String string; // only for string objects
|
||||
boolean stringData; // character array pointed to by a string
|
||||
ObjectItem reference; // object at reference points to this
|
||||
|
||||
ItemList points_to = new ItemList();
|
||||
ItemList pointed_by = new ItemList();
|
||||
}
|
||||
|
||||
private TreeMap<Long, ObjectItem> map = new TreeMap<Long, ObjectItem>();
|
||||
|
||||
public Iterator<Map.Entry<Long, ObjectItem>> iterator()
|
||||
{
|
||||
return map.entrySet().iterator();
|
||||
}
|
||||
|
||||
public ObjectItem get(long ptr)
|
||||
{
|
||||
ObjectItem item = map.get(ptr);
|
||||
return item;
|
||||
}
|
||||
|
||||
public ObjectMap(BufferedReader reader) throws IOException
|
||||
{
|
||||
outer_loop:
|
||||
for (;;)
|
||||
{
|
||||
String s = reader.readLine();
|
||||
if (s == null)
|
||||
break;
|
||||
if (s.indexOf("Begin object map") >= 0)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
s = reader.readLine();
|
||||
if (s.indexOf("End object map") >= 0)
|
||||
break outer_loop;
|
||||
String[] items = s.split(",");
|
||||
ObjectItem item = new ObjectItem();
|
||||
long ptr = 0;
|
||||
for (int i=0; i<items.length; i++)
|
||||
{
|
||||
String[] x = items[i].split(" ");
|
||||
String last = x[x.length-1];
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
item.used = Integer.parseInt(last);
|
||||
break;
|
||||
case 1:
|
||||
ptr = MemoryMap.parseHexLong(last.substring(2));
|
||||
break;
|
||||
case 2:
|
||||
item.size = Integer.parseInt(last);
|
||||
break;
|
||||
case 3:
|
||||
item.kind = Integer.parseInt(last);
|
||||
break;
|
||||
case 4:
|
||||
if (last.length() > 1)
|
||||
item.klass =
|
||||
MemoryMap.parseHexLong(last.substring(2));
|
||||
else
|
||||
item.klass = Integer.parseInt(last,16);
|
||||
break;
|
||||
case 5:
|
||||
try
|
||||
{
|
||||
item.data =
|
||||
Integer.parseInt(last.substring(2), 16);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
item.data = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
item.ptr = ptr;
|
||||
map.put(ptr, item);
|
||||
} // inner loop
|
||||
} // started inner loop
|
||||
} // outer loop - finding begin
|
||||
for (Map.Entry<Long, ObjectItem> me : this)
|
||||
{
|
||||
ObjectItem item = me.getValue();
|
||||
if (item.data != 0)
|
||||
{
|
||||
// see if data is a pointer to a block
|
||||
ObjectItem referenced = map.get(item.data);
|
||||
if (referenced != null)
|
||||
{
|
||||
referenced.reference = item;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // memoryMap
|
||||
|
||||
public void dump()
|
||||
{
|
||||
for (Map.Entry<Long, ObjectItem> me : this)
|
||||
{
|
||||
long ptr = me.getKey();
|
||||
ObjectItem item = me.getValue();
|
||||
System.out.println("ptr = " + Long.toHexString(ptr)
|
||||
+ ", size = " + item.size
|
||||
+ ", klass = " + Long.toHexString(item.klass)
|
||||
+ ", kind = " + item.kind
|
||||
+ ", data = " + item.data);
|
||||
}
|
||||
}
|
||||
}
|
112
libjava/gnu/gcj/tools/gc_analyze/SymbolLookup.java
Normal file
112
libjava/gnu/gcj/tools/gc_analyze/SymbolLookup.java
Normal file
|
@ -0,0 +1,112 @@
|
|||
/* SymbolLookup.java -- Finds class names by analyzing memory.
|
||||
Copyright (C) 2007 Free Software Foundation
|
||||
|
||||
This file is part of libgcj.
|
||||
|
||||
This software is copyrighted work licensed under the terms of the
|
||||
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
|
||||
details. */
|
||||
|
||||
package gnu.gcj.tools.gc_analyze;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
|
||||
class SymbolLookup
|
||||
{
|
||||
MemoryMap memoryMap;
|
||||
|
||||
public SymbolLookup(BufferedReader reader,
|
||||
String rawFileName)
|
||||
throws IOException
|
||||
{
|
||||
memoryMap = new MemoryMap(reader, rawFileName);
|
||||
}
|
||||
|
||||
public String decodeUTF8(long address) throws IOException
|
||||
{
|
||||
return decodeUTF8(address, -1);
|
||||
}
|
||||
|
||||
public String decodeUTF8(long address, int limit) throws IOException
|
||||
{
|
||||
if (address == 0)
|
||||
return null;
|
||||
|
||||
BytePtr utf8 = memoryMap.getBytePtr(address, 64);
|
||||
|
||||
if (utf8 == null)
|
||||
return null;
|
||||
|
||||
int len = utf8.getShort(1);
|
||||
int hash16 = utf8.getShort(0) & 0xffff;
|
||||
|
||||
if (len <= 0 || (limit > 0 && len > (limit - 4)))
|
||||
return null;
|
||||
|
||||
if (len > utf8.getsize() + 4)
|
||||
utf8 = memoryMap.getBytePtr(address, len + 4);
|
||||
|
||||
if (utf8 == null)
|
||||
return null;
|
||||
|
||||
StringBuilder sb = new StringBuilder(len);
|
||||
int pos = 4;
|
||||
len += 4;
|
||||
|
||||
while (pos < len)
|
||||
{
|
||||
int f = utf8.getByte(pos++);
|
||||
if ((f & 0x80) == 0)
|
||||
{
|
||||
sb.append((char)f);
|
||||
}
|
||||
else if ((f & 0xe0) == 0xc0)
|
||||
{
|
||||
int s = utf8.getByte(pos++);
|
||||
char c = (char)(((f & 0x1f) << 6) | (s & 0x80));
|
||||
sb.append(c);
|
||||
}
|
||||
else if ((f & 0xe0) == 0xe0)
|
||||
{
|
||||
int s = utf8.getByte(pos++);
|
||||
int t = utf8.getByte(pos++);
|
||||
char c = (char)(((f & 0x0f) << 12)
|
||||
| ((s & 0x80) << 6) | (t & 0x80));
|
||||
sb.append(c);
|
||||
}
|
||||
else
|
||||
break; // Bad utf8
|
||||
}
|
||||
String rv = sb.toString();
|
||||
if (hash16 == (rv.hashCode() & 0xffff))
|
||||
return rv;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getSymbolViaVtable(long address) throws IOException
|
||||
{
|
||||
return memoryMap.getSymbol(address);
|
||||
}
|
||||
|
||||
public String getSymbol(long address) throws IOException
|
||||
{
|
||||
String symbol = memoryMap.getSymbol(address);
|
||||
if (null != symbol)
|
||||
return symbol;
|
||||
|
||||
BytePtr klass = memoryMap.getBytePtr(address, 3 * memoryMap.wordSize);
|
||||
if (klass == null)
|
||||
return null;
|
||||
|
||||
long nameUTF8p = klass.getWord(2);
|
||||
|
||||
return decodeUTF8(nameUTF8p);
|
||||
}
|
||||
|
||||
BytePtr getBytePtr(long addr, int length) throws IOException
|
||||
{
|
||||
return memoryMap.getBytePtr(addr, length);
|
||||
}
|
||||
}
|
198
libjava/gnu/gcj/tools/gc_analyze/SymbolTable.java
Normal file
198
libjava/gnu/gcj/tools/gc_analyze/SymbolTable.java
Normal file
|
@ -0,0 +1,198 @@
|
|||
/* SymbolTable.java -- Maintains a mapping of addresses to names.
|
||||
Copyright (C) 2007 Free Software Foundation
|
||||
|
||||
This file is part of libgcj.
|
||||
|
||||
This software is copyrighted work licensed under the terms of the
|
||||
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
|
||||
details. */
|
||||
|
||||
package gnu.gcj.tools.gc_analyze;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
class SymbolTable
|
||||
{
|
||||
// Long address->String name
|
||||
private HashMap<Long, String> map = new HashMap<Long, String>();
|
||||
|
||||
// Reverse
|
||||
// String name -> Long address
|
||||
// used for RelocateImage
|
||||
private HashMap<String, Long> reverse = new HashMap<String, Long>();
|
||||
|
||||
long loadAddr;
|
||||
long relocation;
|
||||
|
||||
static Matcher interestingSymbol =
|
||||
Pattern.compile("^([0-9a-fA-F]+)\\s+\\S+\\s+(_Z\\S+)").matcher("");
|
||||
static Matcher readelfLoadMatcher =
|
||||
Pattern.compile("^\\s+LOAD\\s+(\\S+)\\s+(\\S+)\\s.*").matcher("");
|
||||
|
||||
public SymbolTable(String filename) throws IOException
|
||||
{
|
||||
Process p = Runtime.getRuntime().exec(ToolPrefix.toolPrefix
|
||||
+ "nm " + filename);
|
||||
InputStream es = p.getErrorStream();
|
||||
InputStream is = p.getInputStream();
|
||||
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
|
||||
int count = 0;
|
||||
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null)
|
||||
{
|
||||
interestingSymbol.reset(line);
|
||||
if (interestingSymbol.matches())
|
||||
{
|
||||
try
|
||||
{
|
||||
String name = interestingSymbol.group(2);
|
||||
String addr = interestingSymbol.group(1);
|
||||
if (name.startsWith("_ZTVN") || name.endsWith("6class$E"))
|
||||
{
|
||||
long address = MemoryMap.parseHexLong(addr);
|
||||
Long l = new Long(address);
|
||||
map.put(l, name);
|
||||
count++;
|
||||
reverse.put(name, l);
|
||||
}
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
// ignore it
|
||||
}
|
||||
}
|
||||
}
|
||||
es.close();
|
||||
is.close();
|
||||
p.destroy();
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
// Assume nm read some symbols from it and that
|
||||
// readelf can tell us something about how it is loaded.
|
||||
p = Runtime.getRuntime().exec(ToolPrefix.toolPrefix
|
||||
+ "readelf -l " + filename);
|
||||
es = p.getErrorStream();
|
||||
is = p.getInputStream();
|
||||
|
||||
reader = new BufferedReader(new InputStreamReader(is));
|
||||
while ((line = reader.readLine()) != null)
|
||||
{
|
||||
readelfLoadMatcher.reset(line);
|
||||
if (readelfLoadMatcher.matches())
|
||||
{
|
||||
loadAddr
|
||||
= Long.decode(readelfLoadMatcher.group(2)).longValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
es.close();
|
||||
is.close();
|
||||
p.destroy();
|
||||
}
|
||||
|
||||
System.out.println(ToolPrefix.toolPrefix + "nm " + filename
|
||||
+ " -> " + count + " symbols");
|
||||
}
|
||||
|
||||
public static void main(String args[])
|
||||
{
|
||||
try
|
||||
{
|
||||
SymbolTable st = new SymbolTable(args[0]);
|
||||
st.dump();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static String demangleVTName(String n)
|
||||
{
|
||||
if (n.startsWith("_ZTVN") && n.endsWith("E"))
|
||||
return demangle(n.substring(5, n.length() - 1));
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public void dump()
|
||||
{
|
||||
for (Map.Entry<Long, String> me : map.entrySet())
|
||||
{
|
||||
long address = me.getKey();
|
||||
String symbol = me.getValue();
|
||||
System.out.println(Long.toHexString(address) + " -> " + symbol);
|
||||
if (symbol.startsWith("_ZN") && symbol.endsWith("6class$E"))
|
||||
{
|
||||
System.out.println(" Class: "
|
||||
+ demangle(symbol.substring(3, symbol.length()
|
||||
- 8)));
|
||||
}
|
||||
else if (symbol.startsWith("_ZTVN") && symbol.endsWith("E"))
|
||||
{
|
||||
System.out.println(" VT: "
|
||||
+ demangle(symbol.substring(5, symbol.length()
|
||||
- 1)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String demangle(String symbol)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i=0; i<symbol.length(); )
|
||||
{
|
||||
int l = 0;
|
||||
while (i < symbol.length())
|
||||
{
|
||||
int d = symbol.charAt(i);
|
||||
if (d < '0' || d > '9')
|
||||
break;
|
||||
l = 10 * l + (d - '0');
|
||||
i++;
|
||||
}
|
||||
if (l == 0)
|
||||
break;
|
||||
// copy
|
||||
if (sb.length() > 0)
|
||||
sb.append('.');
|
||||
while (l > 0 && i < symbol.length())
|
||||
{
|
||||
sb.append(symbol.charAt(i));
|
||||
l--;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getSymbol(long address)
|
||||
{
|
||||
String symbol = map.get(address);
|
||||
if (symbol == null)
|
||||
return null;
|
||||
|
||||
if (symbol.startsWith("_ZN") && symbol.endsWith("6class$E"))
|
||||
symbol = demangle(symbol.substring(3, symbol.length() - 8));
|
||||
return symbol;
|
||||
}
|
||||
|
||||
// will return -1 if not found
|
||||
public long getAddress(String symbol)
|
||||
{
|
||||
Long address = reverse.get(symbol);
|
||||
if (address == null)
|
||||
return -1;
|
||||
return address.longValue();
|
||||
}
|
||||
}
|
45
libjava/gnu/gcj/tools/gc_analyze/ToolPrefix.java
Normal file
45
libjava/gnu/gcj/tools/gc_analyze/ToolPrefix.java
Normal file
|
@ -0,0 +1,45 @@
|
|||
/* ToolPrefix.java -- Container of the toolPrefix String.
|
||||
Copyright (C) 2007 Free Software Foundation
|
||||
|
||||
This file is part of libgcj.
|
||||
|
||||
This software is copyrighted work licensed under the terms of the
|
||||
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
|
||||
details. */
|
||||
|
||||
package gnu.gcj.tools.gc_analyze;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
class ToolPrefix
|
||||
{
|
||||
/**
|
||||
* Private constructor. No creation allowed. This class has
|
||||
* Static methods only.
|
||||
*/
|
||||
private ToolPrefix()
|
||||
{
|
||||
}
|
||||
|
||||
static String toolPrefix = "";
|
||||
|
||||
static String pathPrefix = "";
|
||||
|
||||
static File fileForName(String filename)
|
||||
{
|
||||
File f = new File(pathPrefix + filename);
|
||||
if (!f.canRead())
|
||||
{
|
||||
// Try it without the prefix.
|
||||
f = new File(filename);
|
||||
if (!f.canRead())
|
||||
{
|
||||
// Try to find it in the current directory.
|
||||
f = new File(f.getName());
|
||||
if (!f.canRead())
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return f;
|
||||
}
|
||||
}
|
45
libjava/gnu/gcj/util/GCInfo.h
Normal file
45
libjava/gnu/gcj/util/GCInfo.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
|
||||
// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*-
|
||||
|
||||
#ifndef __gnu_gcj_util_GCInfo__
|
||||
#define __gnu_gcj_util_GCInfo__
|
||||
|
||||
#pragma interface
|
||||
|
||||
#include <java/lang/Object.h>
|
||||
extern "Java"
|
||||
{
|
||||
namespace gnu
|
||||
{
|
||||
namespace gcj
|
||||
{
|
||||
namespace util
|
||||
{
|
||||
class GCInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class gnu::gcj::util::GCInfo : public ::java::lang::Object
|
||||
{
|
||||
|
||||
GCInfo();
|
||||
static void checkPermission();
|
||||
public:
|
||||
static void dump(::java::lang::String *);
|
||||
private:
|
||||
static void dump0(::java::lang::String *);
|
||||
public:
|
||||
static void enumerate(::java::lang::String *);
|
||||
private:
|
||||
static void enumerate0(::java::lang::String *);
|
||||
public:
|
||||
static void setOOMDump(::java::lang::String *);
|
||||
private:
|
||||
static void setOOMDump0(::java::lang::String *);
|
||||
public:
|
||||
static ::java::lang::Class class$;
|
||||
};
|
||||
|
||||
#endif // __gnu_gcj_util_GCInfo__
|
79
libjava/gnu/gcj/util/GCInfo.java
Normal file
79
libjava/gnu/gcj/util/GCInfo.java
Normal file
|
@ -0,0 +1,79 @@
|
|||
/* GCInfo.java -- Support for creating heap dumps.
|
||||
Copyright (C) 2007 Free Software Foundation
|
||||
|
||||
This file is part of libgcj.
|
||||
|
||||
This software is copyrighted work licensed under the terms of the
|
||||
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
|
||||
details. */
|
||||
|
||||
package gnu.gcj.util;
|
||||
|
||||
public class GCInfo
|
||||
{
|
||||
private GCInfo()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws SecurityException if there is a SecurityManager installed
|
||||
* and UtilPermission("dumpHeap") is not granted.
|
||||
*/
|
||||
private static void checkPermission()
|
||||
{
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null)
|
||||
sm.checkPermission(new UtilPermission("dumpHeap"));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Dump a description of the heap state.
|
||||
*
|
||||
* @param namePrefix The filename prefix for the dump files.
|
||||
*
|
||||
* @throws SecurityException if there is a SecurityManager installed
|
||||
* and UtilPermission("dumpHeap") is not granted.
|
||||
*/
|
||||
public static synchronized void dump(String name)
|
||||
{
|
||||
checkPermission();
|
||||
dump0(name);
|
||||
}
|
||||
|
||||
private static native void dump0(String name);
|
||||
|
||||
|
||||
/**
|
||||
* Create a heap dump.
|
||||
*
|
||||
* @param namePrefix The filename prefix for the dump files.
|
||||
*
|
||||
* @throws SecurityException if there is a SecurityManager installed
|
||||
* and UtilPermission("dumpHeap") is not granted.
|
||||
*/
|
||||
public static synchronized void enumerate(String namePrefix)
|
||||
{
|
||||
checkPermission();
|
||||
enumerate0(namePrefix);
|
||||
}
|
||||
|
||||
private static native void enumerate0(String namePrefix);
|
||||
|
||||
/**
|
||||
* Cause a heap dump if out-of-memory condition occurs.
|
||||
*
|
||||
* @param namePrefix The filename prefix for the dump files. If
|
||||
* null no dumps are created.
|
||||
*
|
||||
* @throws SecurityException if there is a SecurityManager installed
|
||||
* and UtilPermission("dumpHeap") is not granted.
|
||||
*/
|
||||
public static synchronized void setOOMDump(String namePrefix)
|
||||
{
|
||||
checkPermission();
|
||||
setOOMDump0(namePrefix);
|
||||
}
|
||||
|
||||
private static native void setOOMDump0(String namePrefix);
|
||||
}
|
32
libjava/gnu/gcj/util/UtilPermission.h
Normal file
32
libjava/gnu/gcj/util/UtilPermission.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
|
||||
// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*-
|
||||
|
||||
#ifndef __gnu_gcj_util_UtilPermission__
|
||||
#define __gnu_gcj_util_UtilPermission__
|
||||
|
||||
#pragma interface
|
||||
|
||||
#include <java/security/BasicPermission.h>
|
||||
extern "Java"
|
||||
{
|
||||
namespace gnu
|
||||
{
|
||||
namespace gcj
|
||||
{
|
||||
namespace util
|
||||
{
|
||||
class UtilPermission;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class gnu::gcj::util::UtilPermission : public ::java::security::BasicPermission
|
||||
{
|
||||
|
||||
public:
|
||||
UtilPermission(::java::lang::String *);
|
||||
static ::java::lang::Class class$;
|
||||
};
|
||||
|
||||
#endif // __gnu_gcj_util_UtilPermission__
|
20
libjava/gnu/gcj/util/UtilPermission.java
Normal file
20
libjava/gnu/gcj/util/UtilPermission.java
Normal file
|
@ -0,0 +1,20 @@
|
|||
/* GCInfo.java -- Support for creating heap dumps.
|
||||
Copyright (C) 2007 Free Software Foundation
|
||||
|
||||
This file is part of libgcj.
|
||||
|
||||
This software is copyrighted work licensed under the terms of the
|
||||
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
|
||||
details. */
|
||||
|
||||
package gnu.gcj.util;
|
||||
|
||||
import java.security.BasicPermission;
|
||||
|
||||
public class UtilPermission extends BasicPermission
|
||||
{
|
||||
public UtilPermission(String name)
|
||||
{
|
||||
super(name);
|
||||
}
|
||||
}
|
454
libjava/gnu/gcj/util/natGCInfo.cc
Normal file
454
libjava/gnu/gcj/util/natGCInfo.cc
Normal file
|
@ -0,0 +1,454 @@
|
|||
/* natGCInfo.cc -- Native portion of support for creating heap dumps.
|
||||
Copyright (C) 2007 Free Software Foundation
|
||||
|
||||
This file is part of libgcj.
|
||||
|
||||
This software is copyrighted work licensed under the terms of the
|
||||
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
|
||||
details. */
|
||||
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <gcj/cni.h>
|
||||
|
||||
#include <gnu/gcj/util/GCInfo.h>
|
||||
|
||||
#ifdef HAVE_PROC_SELF_MAPS
|
||||
//
|
||||
// If /proc/self/maps does not exist we assume we are doomed and do nothing.
|
||||
//
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
//
|
||||
// Boehm GC includes.
|
||||
//
|
||||
#ifdef PACKAGE_NAME
|
||||
#undef PACKAGE_NAME
|
||||
#endif
|
||||
|
||||
#ifdef PACKAGE_STRING
|
||||
#undef PACKAGE_STRING
|
||||
#endif
|
||||
|
||||
#ifdef PACKAGE_TARNAME
|
||||
#undef PACKAGE_TARNAME
|
||||
#endif
|
||||
|
||||
#ifdef PACKAGE_VERSION
|
||||
#undef PACKAGE_VERSION
|
||||
#endif
|
||||
|
||||
#ifdef TRUE
|
||||
#undef TRUE
|
||||
#endif
|
||||
|
||||
#ifdef FALSE
|
||||
#undef FALSE
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
#include "private/dbg_mlc.h"
|
||||
int GC_n_set_marks(hdr* hhdr);
|
||||
ptr_t GC_clear_stack(ptr_t p);
|
||||
extern int GC_gcj_kind;
|
||||
extern int GC_gcj_debug_kind;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PROC_SELF_MAPS
|
||||
|
||||
static int gc_ok = 1;
|
||||
|
||||
typedef struct gc_debug_info
|
||||
{
|
||||
int used;
|
||||
int free;
|
||||
int wasted;
|
||||
int blocks;
|
||||
FILE* fp;
|
||||
};
|
||||
|
||||
static void
|
||||
GC_print_debug_callback(hblk *h, word user_data)
|
||||
{
|
||||
hdr *hhdr = HDR(h);
|
||||
size_t bytes = WORDS_TO_BYTES(hhdr -> hb_sz);
|
||||
|
||||
gc_debug_info *pinfo = (gc_debug_info *)user_data;
|
||||
|
||||
fprintf(pinfo->fp, "ptr = %#lx, kind = %d, size = %zd, marks = %d\n",
|
||||
(unsigned long)h, hhdr->hb_obj_kind, bytes, GC_n_set_marks(hhdr));
|
||||
}
|
||||
|
||||
/*
|
||||
this next section of definitions shouldn't really be here.
|
||||
copied from boehmgc/allchblk.c
|
||||
*/
|
||||
|
||||
# define UNIQUE_THRESHOLD 32
|
||||
# define HUGE_THRESHOLD 256
|
||||
# define FL_COMPRESSION 8
|
||||
# define N_HBLK_FLS (HUGE_THRESHOLD - UNIQUE_THRESHOLD)/FL_COMPRESSION \
|
||||
+ UNIQUE_THRESHOLD
|
||||
#ifndef USE_MUNMAP
|
||||
extern "C" {
|
||||
extern word GC_free_bytes[N_HBLK_FLS+1];
|
||||
}
|
||||
#endif
|
||||
|
||||
# ifdef USE_MUNMAP
|
||||
# define IS_MAPPED(hhdr) (((hhdr) -> hb_flags & WAS_UNMAPPED) == 0)
|
||||
# else /* !USE_MMAP */
|
||||
# define IS_MAPPED(hhdr) 1
|
||||
# endif /* USE_MUNMAP */
|
||||
|
||||
static void
|
||||
GC_print_hblkfreelist_file(FILE *fp)
|
||||
{
|
||||
struct hblk * h;
|
||||
word total_free = 0;
|
||||
hdr * hhdr;
|
||||
word sz;
|
||||
int i;
|
||||
|
||||
fprintf(fp, "---------- Begin free map ----------\n");
|
||||
for (i = 0; i <= N_HBLK_FLS; ++i)
|
||||
{
|
||||
h = GC_hblkfreelist[i];
|
||||
#ifdef USE_MUNMAP
|
||||
if (0 != h)
|
||||
fprintf (fp, "Free list %ld:\n", (unsigned long)i);
|
||||
#else
|
||||
if (0 != h)
|
||||
fprintf (fp, "Free list %ld (Total size %ld):\n",
|
||||
(unsigned long)i,
|
||||
(unsigned long)GC_free_bytes[i]);
|
||||
#endif
|
||||
while (h != 0)
|
||||
{
|
||||
hhdr = HDR(h);
|
||||
sz = hhdr -> hb_sz;
|
||||
fprintf (fp, "\t0x%lx size %lu ", (unsigned long)h,
|
||||
(unsigned long)sz);
|
||||
total_free += sz;
|
||||
|
||||
if (GC_is_black_listed (h, HBLKSIZE) != 0)
|
||||
fprintf (fp, "start black listed\n");
|
||||
else if (GC_is_black_listed(h, hhdr -> hb_sz) != 0)
|
||||
fprintf (fp, "partially black listed\n");
|
||||
else
|
||||
fprintf (fp, "not black listed\n");
|
||||
|
||||
h = hhdr -> hb_next;
|
||||
}
|
||||
}
|
||||
#ifndef USE_MUNMAP
|
||||
if (total_free != GC_large_free_bytes)
|
||||
{
|
||||
fprintf (fp, "GC_large_free_bytes = %lu (INCONSISTENT!!)\n",
|
||||
(unsigned long) GC_large_free_bytes);
|
||||
}
|
||||
#endif
|
||||
fprintf (fp, "Total of %lu bytes on free list\n", (unsigned long)total_free);
|
||||
fprintf (fp, "---------- End free map ----------\n");
|
||||
}
|
||||
|
||||
static int GC_dump_count = 1;
|
||||
|
||||
static void
|
||||
GC_print_debug_info_file(FILE* fp)
|
||||
{
|
||||
gc_debug_info info;
|
||||
|
||||
memset(&info, 0, sizeof info);
|
||||
info.fp = fp;
|
||||
|
||||
if (gc_ok)
|
||||
GC_gcollect();
|
||||
fprintf(info.fp, "---------- Begin block map ----------\n");
|
||||
GC_apply_to_all_blocks(GC_print_debug_callback, (word)(void*)(&info));
|
||||
//fprintf(fp, "#Total used %d free %d wasted %d\n", info.used, info.free, info.wasted);
|
||||
//fprintf(fp, "#Total blocks %d; %dK bytes\n", info.blocks, info.blocks*4);
|
||||
fprintf(info.fp, "---------- End block map ----------\n");
|
||||
|
||||
//fprintf(fp, "\n***Free blocks:\n");
|
||||
//GC_print_hblkfreelist();
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
class __attribute__ ((visibility ("hidden"))) GC_enumerator
|
||||
{
|
||||
public:
|
||||
GC_enumerator(const char *name);
|
||||
void enumerate();
|
||||
private:
|
||||
FILE* fp;
|
||||
int bytes_fd;
|
||||
|
||||
void print_address_map();
|
||||
void enumerate_callback(struct hblk *h);
|
||||
static void enumerate_callback_adaptor(struct hblk *h, word dummy);
|
||||
};
|
||||
}
|
||||
|
||||
GC_enumerator::GC_enumerator(const char *name)
|
||||
{
|
||||
bytes_fd = -1;
|
||||
fp = fopen (name, "w");
|
||||
if (!fp)
|
||||
{
|
||||
printf ("GC_enumerator failed to open [%s]\n", name);
|
||||
return;
|
||||
}
|
||||
printf ("GC_enumerator saving summary to [%s]\n", name);
|
||||
|
||||
// open heap file
|
||||
char bytes_name[strlen(name) + 10];
|
||||
sprintf (bytes_name, "%s.bytes", name);
|
||||
bytes_fd = open (bytes_name, O_CREAT|O_TRUNC|O_WRONLY, 0666);
|
||||
if (bytes_fd <= 0)
|
||||
{
|
||||
printf ("GC_enumerator failed to open [%s]\n", bytes_name);
|
||||
return;
|
||||
}
|
||||
printf ("GC_enumerator saving heap contents to [%s]\n", bytes_name);
|
||||
}
|
||||
|
||||
/*
|
||||
sample format of /proc/self/maps
|
||||
|
||||
0063b000-00686000 rw-p 001fb000 03:01 81993 /avtrex/bin/dumppropapp
|
||||
00686000-0072e000 rwxp 00000000 00:00 0
|
||||
|
||||
These are parsed below as:
|
||||
start -end xxxx xxxxxxxx a:b xxxxxxxxxxxxxxx
|
||||
|
||||
*/
|
||||
|
||||
|
||||
void
|
||||
GC_enumerator::print_address_map()
|
||||
{
|
||||
FILE* fm;
|
||||
char buffer[128];
|
||||
|
||||
fprintf(fp, "---------- Begin address map ----------\n");
|
||||
|
||||
fm = fopen("/proc/self/maps", "r");
|
||||
if (fm == NULL)
|
||||
{
|
||||
if (0 == strerror_r (errno, buffer, sizeof buffer))
|
||||
fputs (buffer, fp);
|
||||
}
|
||||
else
|
||||
{
|
||||
while (fgets (buffer, sizeof buffer, fm) != NULL)
|
||||
{
|
||||
fputs (buffer, fp);
|
||||
char *dash = strchr(buffer, '-');
|
||||
char *colon = strchr(buffer, ':');
|
||||
if (dash && colon && ((ptrdiff_t)strlen(buffer) > (colon - buffer) + 2))
|
||||
{
|
||||
char *endp;
|
||||
unsigned long start = strtoul(buffer, NULL, 16);
|
||||
unsigned long end = strtoul(dash + 1, &endp, 16);
|
||||
unsigned long a = strtoul(colon - 2, NULL, 16);
|
||||
unsigned long b = strtoul(colon + 1, NULL, 16);
|
||||
// If it is an anonymous mapping 00:00 and both readable
|
||||
// and writeable then dump the contents of the mapping
|
||||
// to the bytes file. Each block has a header of three
|
||||
// unsigned longs:
|
||||
// 0 - The number sizeof(unsigned long) to detect endianness and
|
||||
// structure layout.
|
||||
// 1 - The offset in VM.
|
||||
// 2 - The Length in bytes.
|
||||
// Followed by the bytes.
|
||||
if (!a && !b && endp < colon && 'r' == endp[1] && 'w' == endp[2])
|
||||
{
|
||||
unsigned long t = sizeof(unsigned long);
|
||||
write(bytes_fd, (void*)&t, sizeof(t));
|
||||
write(bytes_fd, (void*)&start, sizeof(start));
|
||||
t = end - start;
|
||||
write(bytes_fd, (void*)&t, sizeof(t));
|
||||
write(bytes_fd, (void*)start, (end - start));
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(fm);
|
||||
}
|
||||
fprintf(fp, "---------- End address map ----------\n");
|
||||
fflush(fp);
|
||||
}
|
||||
|
||||
void
|
||||
GC_enumerator::enumerate()
|
||||
{
|
||||
print_address_map();
|
||||
fprintf(fp, "---------- Begin object map ----------\n");
|
||||
if (gc_ok)
|
||||
GC_gcollect();
|
||||
GC_apply_to_all_blocks(enumerate_callback_adaptor,
|
||||
(word)(void*)(this));
|
||||
fprintf(fp, "---------- End object map ----------\n");
|
||||
fflush(fp);
|
||||
|
||||
GC_print_debug_info_file(fp);
|
||||
fflush(fp);
|
||||
GC_print_hblkfreelist_file(fp);
|
||||
fflush(fp);
|
||||
|
||||
close(bytes_fd);
|
||||
fclose(fp);
|
||||
|
||||
GC_clear_stack(0);
|
||||
}
|
||||
|
||||
void
|
||||
GC_enumerator::enumerate_callback_adaptor(struct hblk *h,
|
||||
word dummy)
|
||||
{
|
||||
GC_enumerator* pinfo = (GC_enumerator*)dummy;
|
||||
pinfo->enumerate_callback(h);
|
||||
}
|
||||
|
||||
void
|
||||
GC_enumerator::enumerate_callback(struct hblk *h)
|
||||
{
|
||||
hdr * hhdr = HDR(h);
|
||||
size_t bytes = WORDS_TO_BYTES(hhdr->hb_sz);
|
||||
int i;
|
||||
|
||||
for (i = 0; i == 0 || (i + bytes <= HBLKSIZE); i += bytes)
|
||||
{
|
||||
int inUse = mark_bit_from_hdr(hhdr,BYTES_TO_WORDS(i)); // in use
|
||||
char *ptr = (char*)h+i; // address
|
||||
int kind = hhdr->hb_obj_kind; // kind
|
||||
void *klass = 0;
|
||||
void *data = 0;
|
||||
if (kind == GC_gcj_kind
|
||||
|| kind == GC_gcj_debug_kind
|
||||
|| kind == GC_gcj_debug_kind+1)
|
||||
{
|
||||
void* v = *(void **)ptr;
|
||||
if (v)
|
||||
{
|
||||
klass = *(void **)v;
|
||||
data = *(void **)(ptr + sizeof(void*));
|
||||
}
|
||||
}
|
||||
if (inUse)
|
||||
fprintf (fp, "used = %d, ptr = %#lx, size = %zd, kind = %d, "
|
||||
"klass = %#lx, data = %#lx\n",
|
||||
inUse, (unsigned long)ptr, bytes, kind,
|
||||
(unsigned long)klass, (unsigned long)data);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill in a char[] with low bytes of the string characters. These
|
||||
* methods may be called while an OutOfMemoryError is being thrown, so
|
||||
* we cannot call nice java methods to get the encoding of the string.
|
||||
*/
|
||||
static void
|
||||
J2A(::java::lang::String* str, char *dst)
|
||||
{
|
||||
jchar * pchars = JvGetStringChars(str);
|
||||
jint len = str->length();
|
||||
int i;
|
||||
for (i=0; i<len; i++)
|
||||
dst[i] = (char)pchars[i];
|
||||
dst[i] = 0;
|
||||
}
|
||||
|
||||
void
|
||||
::gnu::gcj::util::GCInfo::dump0 (::java::lang::String * name)
|
||||
{
|
||||
char n[name->length() + 1];
|
||||
J2A(name, n);
|
||||
|
||||
char temp[name->length() + 20];
|
||||
sprintf(temp, "%s%03d", n, GC_dump_count++);
|
||||
FILE* fp = fopen(temp, "w");
|
||||
|
||||
GC_print_debug_info_file(fp);
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
void
|
||||
::gnu::gcj::util::GCInfo::enumerate0 (::java::lang::String * name)
|
||||
{
|
||||
char n[name->length() + 1];
|
||||
J2A(name, n);
|
||||
char temp[name->length() + 20];
|
||||
sprintf(temp, "%s%03d", n, GC_dump_count++);
|
||||
|
||||
GC_enumerator x(temp);
|
||||
x.enumerate();
|
||||
}
|
||||
|
||||
static char *oomDumpName = NULL;
|
||||
|
||||
static void *
|
||||
nomem_handler(size_t size)
|
||||
{
|
||||
if (oomDumpName)
|
||||
{
|
||||
char temp[strlen(oomDumpName) + 20];
|
||||
sprintf(temp, "%s%03d", temp, GC_dump_count++);
|
||||
printf("nomem_handler(%zd) called\n", size);
|
||||
gc_ok--;
|
||||
GC_enumerator x(temp);
|
||||
x.enumerate();
|
||||
gc_ok++;
|
||||
}
|
||||
return (void*)0;
|
||||
}
|
||||
|
||||
void
|
||||
::gnu::gcj::util::GCInfo::setOOMDump0 (::java::lang::String * name)
|
||||
{
|
||||
char *oldName = oomDumpName;
|
||||
oomDumpName = NULL;
|
||||
free (oldName);
|
||||
|
||||
if (NULL == name)
|
||||
return;
|
||||
|
||||
char *n = (char *)malloc(name->length() + 1);
|
||||
|
||||
J2A(name, n);
|
||||
oomDumpName = n;
|
||||
GC_oom_fn = nomem_handler;
|
||||
}
|
||||
|
||||
#else // HAVE_PROC_SELF_MAPS
|
||||
|
||||
void
|
||||
::gnu::gcj::util::GCInfo::dump0 (::java::lang::String * name)
|
||||
{
|
||||
// Do nothing if dumping not supported.
|
||||
}
|
||||
|
||||
void
|
||||
::gnu::gcj::util::GCInfo::enumerate0 (::java::lang::String * name)
|
||||
{
|
||||
// Do nothing if dumping not supported.
|
||||
}
|
||||
|
||||
void
|
||||
::gnu::gcj::util::GCInfo::setOOMDump0 (::java::lang::String * name)
|
||||
{
|
||||
// Do nothing if dumping not supported.
|
||||
}
|
||||
|
||||
#endif // HAVE_PROC_SELF_MAPS
|
||||
|
|
@ -232,6 +232,9 @@
|
|||
/* Define if you have /proc/self/exe */
|
||||
#undef HAVE_PROC_SELF_EXE
|
||||
|
||||
/* Define if you have /proc/self/maps */
|
||||
#undef HAVE_PROC_SELF_MAPS
|
||||
|
||||
/* Define if using POSIX threads that have the mutexattr functions. */
|
||||
#undef HAVE_PTHREAD_MUTEXATTR_INIT
|
||||
|
||||
|
@ -375,6 +378,9 @@
|
|||
/* Define to 1 if you have the file `AC_File'. */
|
||||
#undef HAVE__PROC_SELF_EXE
|
||||
|
||||
/* Define to 1 if you have the file `AC_File'. */
|
||||
#undef HAVE__PROC_SELF_MAPS
|
||||
|
||||
/* Define as const if the declaration of iconv() needs const. */
|
||||
#undef ICONV_CONST
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ set package_map(.) package
|
|||
# These are ignored in Classpath.
|
||||
set package_map(gnu/test) ignore
|
||||
set package_map(gnu/javax/swing/plaf/gtk) ignore
|
||||
set package_map(gnu/gcj/tools/gc_analyze) ignore
|
||||
|
||||
set package_map(gnu/java/awt/peer/swing) bc
|
||||
|
||||
|
|
|
@ -555,7 +555,9 @@ gnu/gcj/tools/gcj_dbtool.list: $(gnu_gcj_tools_gcj_dbtool_source_files)
|
|||
|
||||
|
||||
gnu_gcj_util_source_files = \
|
||||
gnu/gcj/util/Debug.java
|
||||
gnu/gcj/util/Debug.java \
|
||||
gnu/gcj/util/GCInfo.java \
|
||||
gnu/gcj/util/UtilPermission.java
|
||||
|
||||
gnu_gcj_util_header_files = $(patsubst %.java,%.h,$(gnu_gcj_util_source_files))
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue