Guice is hiding binding errors until requested?

68 views
Skip to first unread message

glenviewjeff

unread,
Jul 24, 2012, 3:05:08 PM7/24/12
to google...@googlegroups.com
I started doing a memory analysis of my Android app and was quite surprised to find that in memory there were a bunch of Java strings holding binding errors inside a child injector.  These errors are apparently not reported upon injector creation.  I wrote unit tests for the erroneous bindings and as expected, they caused a runtime binding error. 

It looks like the errors are stored in memory after constructing the injector but only thrown when a client object requests that the erroneous object is be injected.  My integration tests somehow didn't pick up these binding errors and the errors are wasting significant runtime memory.

Running and poking around through memory dumps is not a terribly feasible way to find these.  Is there a strict error checking/reporting feature for Guice to give me the information on all broken bindings at the time the injector is created?  Is there a reason this isn't the default behavior?


glenviewjeff

unread,
Jul 24, 2012, 3:29:23 PM7/24/12
to google...@googlegroups.com
I looked a little more carefully and it seems that things are much worse than I thought.  These are more like "phantom" binding errors.  Guice is apparently doing some analysis at injector creation time--it's pre-constructing and storing in memory what appears to be all potential binding errors, even if the errors don't actually exist in the code.

For instance, there is a binding error stored in memory in the event that an object is requested that was bound but not exposed in a private module (robot legs).  Of course, that's the whole purpose of private modules.  I assume Guice does this because once the injector is created, it never wants to look at the modules again, but needs to have the error available in case someone tries to access a private unexposed object?

I guess it ends up that I don't want a strict error checking mode, I actually want a "release mode" or something, where Guice doesn't construct these "errors"! 

I'm not sure if this would even be possible, but better yet would be to fix Guice so that upon binding error, it could recreate the injector (re-parsing the modules, etc.) to find the cause of the error.

Sam Berlin

unread,
Jul 24, 2012, 4:02:56 PM7/24/12
to google...@googlegroups.com

Can you create an issue an attach a test that shows the problem?

--
You received this message because you are subscribed to the Google Groups "google-guice" group.
To view this discussion on the web visit https://groups.google.com/d/msg/google-guice/-/SH0BfcTZ6zYJ.
To post to this group, send email to google...@googlegroups.com.
To unsubscribe from this group, send email to google-guice...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/google-guice?hl=en.

glenviewjeff

unread,
Jul 25, 2012, 12:17:58 AM7/25/12
to google...@googlegroups.com
I spent several hours trying to create a straight native Java Guice sample that shows the problem, and then subsequently tried to show it with a simple RoboGuice app.  I couldn't find the binding error messages on the heap in either sample.  I'll put in a little more effort to try to reproduce it, but probably put this aside after that since the heap is still only ~3MB. 

As a start, here's just one of the errors I found laying around in the heap using Eclipse's MAT.  There are many more but I can't easily count them.  Please excuse the long and wrapped lines.

                                 | Shallow Heap | Retained Heap | Percentage
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
com.google.inject.internal.InjectorImpl @ 0x40636dd0                                                                                                                                                                                                                                                                         |           48 |       377,504 |     11.06%
|- com.google.inject.internal.ConstructorInjectorStore @ 0x40636ea0                                                                                                                                                                                                                                                          |           16 |        62,968 |      1.84%
|  '- com.google.inject.internal.ConstructorInjectorStore$1 @ 0x40636eb8                                                                                                                                                                                                                                                     |           16 |        62,952 |      1.84%
|     '- com.google.inject.internal.util.$CustomConcurrentHashMap$ComputingImpl @ 0x40636f38                                                                                                                                                                                                                                 |           56 |        62,936 |      1.84%
|        |- com.google.inject.internal.util.$CustomConcurrentHashMap$Impl$Segment[16] @ 0x40636f78                                                                                                                                                                                                                           |           80 |        62,816 |      1.84%
|        |  |- com.google.inject.internal.util.$CustomConcurrentHashMap$Impl$Segment @ 0x406371b0                                                                                                                                                                                                                            |           32 |        15,000 |      0.44%
|        |  |  |- java.util.concurrent.atomic.AtomicReferenceArray @ 0x4061c6d8                                                                                                                                                                                                                                              |           16 |        14,944 |      0.44%
|        |  |  |  '- java.lang.Object[4] @ 0x40658898                                                                                                                                                                                                                                                                        |           32 |        14,928 |      0.44%
|        |  |  |     '- com.google.inject.internal.util.$MapMaker$LinkedStrongEntry @ 0x406588c0                                                                                                                                                                                                                             |           32 |        14,896 |      0.44%
|        |  |  |        |- com.google.inject.internal.util.$MapMaker$LinkedStrongEntry @ 0x40600070                                                                                                                                                                                                                          |           32 |        13,160 |      0.39%
|        |  |  |        |- java.lang.String @ 0x40603d28  Unable to create binding for com.[...myclass...]. It was already configured on one or more child injectors or private modules\u000a    (bound by a just-in-ti...|           24 |           952 |      0.03%
Reply all
Reply to author
Forward
0 new messages