2

I have about 55 Java interfaces and 5 abstract classes. Each declaration uses the same set of generic parameters: it lists the approximately 60 declarations so each implementation knows a specific type of each other implementation and substitute this type in method parameters and returns as appropriate. It appears that this (perhaps over)use of generics is causing the compiler to hang. The compiler throws an OutOfMemoryError, but does not appear to terminate.

Considering my circumstance, a code listing comprising even one of these declarations is a little difficult, but a part of a listing might be possible. The interface declarations commonly specify a collection of about five methods, but the use of generics in the declaration increases the size of a source module to about a thousand lines.

Could my case be a case of the compiler actually going into an infinite loop, or should I just give it more memory? It takes about 20 minutes for the OutOfMemoryError exception to be thrown, so I'm concerned that if I just increase the memory given to the compiler by a factor, it will just take that factor longer for the compiler to throw the exception.

I'm using NetBeans as my editor environment, but have been resorting to running the clean/build script as soon as I start NetBeans. I do this because NetBeans quickly becomes unresponsive when it begins to check the syntax of my code after start-up. I'm using Ubuntu 10.4 (I think - I'm writing this from Windows). I have resorted to opening a command line in the Ubuntu environment, running NetBeans as a background process, checking the output and correcting any source code mistakes using gedit, killing and then restarting NetBeans. This appeared to suffice until I found that no more syntax errors were being produced. I don't know how to run the clean/build script from the command line.

Sorry if this question appears vague, but if others could help me then maybe I could be a little more specific.

Thanks for any considered advice.

  • How many source files are there? – fge Jan 02 '13 at 00:30
  • Regardless of whether this is hanging the compiler, this sounds horrible. – Oliver Charlesworth Jan 02 '13 at 00:31
  • 1
    I'm sorry, but I just can't imagine what you are describing. Could you provide a cut-down listing that demonstrates your technique (for lack of a better word)? Perhaps something with single-letter class names? – thkala Jan 02 '13 at 00:34
  • Try to give compiler more memory! – Dims Jan 02 '13 at 00:38
  • Also, you can compile file by file and look what file causes hang or endless loop – Dims Jan 02 '13 at 00:39
  • @OliCharlesworth: Agreed. Code that cannot be broken down even to provide a partial listing is horrible. Code idioms that cannot be described in a single paragraph are horrible. Code that breaks the compiler is in 99.999999% of all cases broken by design. Code that does all three... well... – thkala Jan 02 '13 at 00:41
  • @OwenThomas: I'm sorry, but unless you can convince me otherwise, I'd say that what you need is a *major* refactoring - no amount of compiler tweaks, coaxing or prayer is going to fix code that breaks the compiler out of sheer complexity. If the compiler can't parse it, how do you expect a human to? – thkala Jan 02 '13 at 00:47
  • @OwenThomas: now that I am thinking about it... is this code generated automatically? And if yes, how exactly is it generated? – thkala Jan 02 '13 at 00:49
  • Hmmm... I think I can give a cut-down version of a listing. I'll get back to this. A probable source of trouble about my generic declarations is that they're self referential; one declaration refers to another which refers to the first. There are even scenarios where the declaration refers to itself. I had successfully avoided realising my fear of an infinite regress for some years, but now my fears may have been realised. –  Jan 02 '13 at 01:08
  • 1
    Can you post a link to a snippet of one of these declarations? Honestly I just want to gawk. – Paul Bellora Jan 02 '13 at 10:51

1 Answers1

3

It sounds to me like you've got some overly complicated use of generics, and this is causing the Java compiler to use an excessive amount of memory trying to represent the expansions of the generic types. The very long times before failure are probably due to a "garbage collection death spiral" ... where the GC spends more and more time, reclaiming less and less memory each time, until it finally has to give up.

If you can't show us the code, the only possible suggestion is to run the compiler with a larger heap, and see if that cures the problem.

I don't know how to run the clean/build script from the command line.

Well, I think you need to figure that out. It may help you solve the problem, and it is important to know these things anyway; e.g. so that you can use a CI system to build your code and run your tests. (And you will probably need to run the script from the command line to get the build to run in a separate JVM with a heap whose size you can control independently of your IDE.)


It is also possible that your complicated use of generics includes something pathological (and probably nonsensical) that the Java compiler cannot cope with.

A probable source of trouble about my generic declarations is that they're self referential; one declaration refers to another which refers to the first.

Yea ... that's the kind of thing that I'm talking about. If you are not careful, you can end up with something that is meaningless (from a Java perspective) that involves infinite type expansions.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • I don't think it's possible to have "infinite type expansions". – newacct Jan 02 '13 at 03:30
  • What I'm trying to do is to complete a pattern of circular reference from one interface through all others and back to itself. My project is the implementation of an idea I have had for several years, and this idea is based around a system that defines the notion of a self. It might be that Java is unable to model such notions, or it may also be that my notions are not algorithmic in nature. I've been for a walk, and have deliberated other possibilities. I'm going to follow a few other leads at the moment. Thanks for your time. –  Jan 02 '13 at 03:37
  • 1
    @OwenThomas - I think you may be expecting too much of Java. It is a programming language ... not a system for modelling types. – Stephen C Jan 02 '13 at 06:34
  • @OwenThomas Your problem reminds me of this [simpler question](http://stackoverflow.com/questions/9423047/cyclical-generics-try-2) and my answer to it. Not sure how much it's related. – Paul Bellora Jan 02 '13 at 10:44
  • @StephenC I think I'm discovering this. I chose Java because I know of only a relative few language environments, and of them, Java seemed to be the most capable. Maybe if I had a wider knowledge, I might have made a more informed choice. Perhaps, Java is still a good choice because it is a widely supported language, and it has other features that my implementation draws on. –  Jan 02 '13 at 12:36
  • @PaulBellora - It does seem to be like my problem, only yours is far, far simpler. In my situation, I'm exhaustively combining interface and abstract class definitions in each of these almost 60 declarations. I think I've distilled interface hell. In places, it appears that I cannot avoid the use of wild-cards. This is unlike your example, and I'm getting the feeling that this could be tangling the compiler. I'm going to have to become more circumspect in my use of wild-cards. –  Jan 02 '13 at 13:16