3

=== Conclusion ====

found a good read at https://softwareengineering.stackexchange.com/a/149569 which states

Current GC algorithms are actually optimized for creating many many small objects that are short lived, So I think using anonymous inner class a lot in project would not be a big deal regarding to performance*

========================================================================

Because function is not the first class citizen in current Java(Java7), using anonymous inner class seems the only way to implement full async application.

I know it will bring larger memory footprint and burden garbage collector in some extent, but I don't know how serious it could be? Recently my colleague argued with me because my code was written in functional style by leveraging anonymous inner class, his objection was all about performance. Though I don't agree, I can't cite any example to prove myself. I know groovy is implementing closure all using anonymous class, but groovy does have poorer performance than java(of course anonymous should only take part of responsibility, as groovy heavily uses reflection as well).

so I wonder in real world, is there any project dropping anonymous class just because performance? how about UI framework like swing? Is it using anonymous class massively?

without anonymous, I can't imagine how to implement async elegantly in java. our project already uses a very ugly way to make class method work as function pointer. I hate that much and want to convince people anonymous class is the right way to go.

My Example:

// basically, I use Completion interface to make normal java methods work in async manner

public interface Completion {
    void success();

    void fail(String reason);
}


void methodA(Completion completion) {

     do_some_business_by_calling_remote_service ....

     when remote_service_ack_success:
         completion.success();
     else:
         completion.fail(remote_service_error);

}

void methodB() {
    methodA(new Completion() {
       public void success() {
           continue to do something;
       }

       public void fail(String err) {
           handle error
       }
    });
}
Community
  • 1
  • 1
zx_wing
  • 1,918
  • 3
  • 26
  • 39
  • Can you provide an example of just how you're using anonymous classes, and what performance issues it is that worry you? – Dolda2000 Jan 09 '14 at 00:57
  • @Dolda2000: see my updates – zx_wing Jan 09 '14 at 01:07
  • 1
    You're not the first to have this question: [StackOverflow - Java anonymous class efficiency implications](https://stackoverflow.com/questions/3028341/java-anonymous-class-efficiency-implications) – J.P. Armstrong Jan 09 '14 at 01:18
  • @J.P.: NO it's different. the thread you post has no different on performance given it will create an object anyway no mater using anonymous class or inner class. My case is different, it creates anonymous object for every method call which is not necessary in sync call manner – zx_wing Jan 09 '14 at 01:22
  • @zx_wing observing the out comes of javac, anonymous inner classes are not created during runtime. They are compiled just as any other inner classes, except that the class name will be determined by the compiler. **It does not create a new class on every method call**. – TwilightSun Jan 09 '14 at 01:25
  • @TwilightSun: thanks for pointing out. Actually I mean an anonymous object. I have updated my last comment. – zx_wing Jan 09 '14 at 01:27
  • This debating question maybe will help you:http://stackoverflow.com/questions/2284396/java-anonymous-or-not-inner-classes-is-it-good-to-use-them. In my own opinion, inner classes themselves are not evil. Java is a language concerning more on project management than to performance. So if anonymous classes and functional like programing helps you to make your project more robust and easy to maintain, use it. – TwilightSun Jan 09 '14 at 01:28
  • 2
    @zx_wing There is no concept of "Anonymous object" – cat916 Jan 09 '14 at 01:39
  • In Java, if performance is what you care about, avoid creating unnecessary **objects** not classes. Avoid using *foreach* loops for( : ) when iterating builtin arrays because it's creating a iterator object. Avoid using object counter parts of the primitive types such as Integer or Boolean because they create objects. And blah, blah, blah, my impression to this is, if one cares so much about performance and try as hard as possible to avoid the gifts of Java, why don't give up Java and use C/C++ instead. – TwilightSun Jan 09 '14 at 01:39
  • @TwilightSun: it's good point. I also used it as my argument in debate. – zx_wing Jan 09 '14 at 01:45
  • @minhcat_vo: yes I know. I just want to describe the object created from anonymous class – zx_wing Jan 09 '14 at 01:45
  • @TwilightSun For each doesn't create an Iterator when used with arrays. It gets compiled almost identically to a regular for loop. For each only uses an Iterator when used with an Iterable. – Radiodef Jan 09 '14 at 02:06
  • What's the current way that your project implements function pointers? – Nam San Jan 09 '14 at 02:10
  • @NamSan: in short words it's actually using reflection to invoke a method. instead of passing a anonymous class you pass method name and parameters – zx_wing Jan 09 '14 at 02:23
  • You can be sure that reflections will cause more performance drop than anonymous classes. Anonymous classes has no performance difference than normal private inner classes, because they are mostly the same thing. And inner classes themselves will not cause any performance drop down if you can't eliminate the object instancing. But you do have to notice that if A passes an instance of an anonymous object to B, and B keeps it, then B will be referencing A so A will not be garbage collected if B is still active. – TwilightSun Jan 09 '14 at 02:36
  • @TwilightSun Yep, interfaces are a way better way to "pass a function" than using reflection. And to boot, reflection creates an object too. – Radiodef Jan 09 '14 at 03:41
  • guys, just found a good read at http://programmers.stackexchange.com/a/149569 – zx_wing Jan 09 '14 at 04:39
  • @zx_wing That is a pretty definitive-seeming answer and Java object creation/GC is indeed generally really efficient. That's the basis of my opinion. Sure, you are creating a new object for each invocation, but the syntax is perhaps more clear. In general maintainability trumps optimization unless the maintainable code is actually a problem. In this case it's probably negligible. – Radiodef Jan 09 '14 at 07:25

1 Answers1

8

There's basically two issues here, neither of them really have to do with the anonymous aspect. Anonymous classes aren't really any different than regular inner classes except that they don't have a name. An anonymous inner class gets compiled to a regular inner class, which in turn is still not really any different from a static nested class.

Issue 1 is that since they are inner, they keep a reference to the enclosing class:

class Outer {
    interface Inner {}

    Inner inner = new Inner() {
        {
            System.out.println(Outer.this);
        }
    };
}

This is not so much an issue and most of the time it's desired because you are doing something functional and want to use the outer instance's members inside the inner class. But it could create problems since as long as the inner class is alive, the outer class can't be garbage collected.

Issue 2 is that indeed they are an object so indeed your methodB is creating a new one each time it's called.

The obvious solution is just to create it once:

class MyProcess {

    final Completion myCompletion = new Completion() {
        @Override
        public void success() {}
        @Override
        public void fail(String err) {}
    }

    void methodA(Completion c) {}

    void methodB() {
        methodA(myCompletion);
    }
}

It seems like what you like is the syntax though and there's not really a solution to keep the syntax and not create an object at the same time.

My personal opinion: if you aren't calling this method a lot, I agree the syntax can be nice and clear. If you are calling it a lot, switch to a single object because you are crowding memory space. If it gets called 1000 times, that's 1000 objects. Object size differs by platform, but it's typically a minimum 8 or 16 bytes + a pointer to the outer instance. That's not a huge impact but it could, for example, prompt garbage collection to run which can cause subtle stalling.

By the way, I was thinking about this again and thought of the following idea:

Completion myLazyCompletion;

void methodB() {
    methodA(myLazyCompletion != null ? myLazyCompletion :
        (myLazyCompletion = new Completion() {

            // overrides

        })
    );
}

I would say don't do that, but I thought it was interesting. : )

Radiodef
  • 37,180
  • 14
  • 90
  • 125
  • yes. now it seems the only problem is anonymous class may cause too many objects. just wondering how UI framework project handles it, defining it outside method scope seems not a good way to make good readable – zx_wing Jan 09 '14 at 02:45
  • It would be nice if Java's memory management was a little more explicit since this is an obvious scenario for stack allocation. Supposedly a JVM can do escape analysis and do it but it would be a silent optimization. Stack allocation would make the object comparatively free. – Radiodef Jan 09 '14 at 03:36
  • @Radiodef: the lazy creating is not right. the advantage of anonymous class is not only using as callback, but also having hidden references to variables(local or class wide) defined in the same scope. this reference binding is huge convenient that people use it a lot as functional style. using an inner class instead of anonymous class makes no way to bind to local variables of method where anonymous class usually created. using the lazy creating method makes it even worse, as the object only binds to variables the first time it created. – zx_wing Jan 09 '14 at 09:21
  • @zx_wing I never said it was the exact same thing--actually I said not to do it. – Radiodef Jan 09 '14 at 09:34