Skip to main content

Optimize public final static constants at load time

22 replies [Last post]
regexguy
Offline
Joined: 2003-06-20

I wish that the compiler would not optimize references to public final static constants at compile time -- load time would be a lot more convenient.

This would basically make it easier to build with ant, etc. as well as avoid weird behavior when you execute an out of date class file.

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
dgriffit
Offline
Joined: 2004-10-13

Most Java development is not IDE plugins, but most Java development does use third-party libraries, those third-party libraries do expose constants, and those constants are subject to change between library releases. Scattering version-check code throughout every code base that uses a constant from a library seems a bit excessive. This JVM misfeature is a known cause of difficult to track-down bugs. It's also just about the only thing left which causes developers to have to do non-incremental rebuilds on a daily basis. It's worth fixing, if the cost is small.

patrikbeno
Offline
Joined: 2004-10-11

Agreed. Well said.
And it's worth fixing because the cost is small - just to comment out some 'if (isFinalConstant()) { doOptimize(); }'
And even if it was a little higher than that, it should be fixed because it saves the time of many other people

dgriffit
Offline
Joined: 2004-10-13

It is a touch more than that, as the lookupswitch and tableswitch JVM bytecode implementations need to be made to work with constants that are unknown at compile time. This might have runtime costs.

mthornton
Offline
Joined: 2003-06-10

Of course if you declare your constants in that way you can't use them in case statements. The load time advantage is probably only significant on small devices and perhaps it should have been implemented as a post process of the byte code (if at all) that was only done where necessary.

Now that Tiger has been released, the better work around may be to use enum's instead --- these can be used in case statements despite their value only being determined at load time.

Message was edited by: mthornton

dgriffit
Offline
Joined: 2004-10-13

I had assumed part of this request was also allowing switch statements to work agains load-time constants. There will be a run-time hit for this, but that's a tradeoff. There is then an issue as to what should happen if two load-time case branches have the same value, but I would say that's just another validation error.

ricky_clarkson
Offline
Joined: 2004-06-28

Most Java work is not IDE plugins. If it was, there'd be something [b]seriously[/b] wrong.

Most people do full rebuilds, and shouldn't have to suffer because plug-in writers can't be bothered to include a check such as:

if (Idea.getVersion()>whateverVersionICompiledAgainst)
complainAndDie()

Of course, you'd need to make sure that you use Idea.getVersion() and not Idea.VERSION :)

patrikbeno
Offline
Joined: 2004-10-11

Again please explain how would those people doing full rebuilds [b]suffer[/b] if this proposal was implemented?

Besides this, if you have project wiht thousands classes, you have to do incremental builds at development time or your compilations would last 2/8 of your working time

dgriffit
Offline
Joined: 2004-10-13

A concrete example, to clarify. I write a plugin, let's call it InspectionGadgets, for a third-party product, call it IntelliJ IDEA. My plugin uses some constants declared in an IDEA jar (representing, for example, types of Java tokens in their parse tree). Between releases, the team writing IntelliJ IDEA changes the values of some of those constants. Existing copies of my plugin compiled before the change will still run, but will give wrong results, making me look foolish. It's not that I released bad code or that the IDEA team released bad code, it's just that users will inadvertantly use code that is unnecessarily incompatible. There's no real reason the code needs to be incompatible, beyond this "gotcha" in the Java spec. The "gotcha" is only their for performance reasons, and the requestor is asserting those just aren't good enough anymore. I'm inclined to agree.

patrikbeno
Offline
Joined: 2004-10-11

For deploy, I do full rebuild.
At development time, I do incremental builds.

Point is that incremental builds (using javac) are just unreliable when you change value of the final constant.

But think about this:
- you can exchange jar file with new bugfixed method implementation (but same API) and things just work fine withou recompilation
- you can change value of the 'static public int' variable in a class in that JAR file, and things work without recompilation
- but things stop working when you decide to make that variable 'final'

Further, consider this:
[code]
public class Main {
static public void main(String[] args) {
System.out.println(Const.INT);
}
}

class Const { static public final int INT = 1; }
[/code]

as you see, Main refers to and prints Const.INT value. But you can safely run Main class without having Const class on the classpath.

Don't you find it all just too weird?

Message was edited by: patrikbeno

tsinger
Offline
Joined: 2003-06-10

Could you please elaborate a little bit? What is the major difference between compilation and deployment for you?

--
Thanks in advance,
Tom

regexguy
Offline
Joined: 2003-06-20

Suppose I write libA.jar, and it uses libB.jar that is built by someone else. Suppose there is a public final static constant in libB.jar that changes from version 1.0 to version 1.1.

I want my library to work with either version 1.0 or 1.1. In order to accomplish this, I have to use refelction to grab the value (because the compiler seems to always optimize this), and that may not even be possible for some security settings.

So this means that I cannot make a libA.jar work with two versions of libB.jar unless libB.jar just stops using constants.

It's ugly.

regexguy
Offline
Joined: 2003-06-20

assert() statements are examples of load time optimizations. I have yet to notice the difference in startup time for my applications for using the -ea flag to the JVM. I don't think performances is an issue.

zander
Offline
Joined: 2003-06-13

Its something you really must be aware of, I agree.

But if you are, its a valuable thing to have since it makes loading of classes faster and allows partial deployment.

Perhaps for the ones who think otherwise; here is code to allow you to make sure your final [basetype] variables are not placed in the generated .class file:
[code]
class MyClass {
public static final int integer;
static {
integer = 1;
}
}
[/code]

patrikbeno
Offline
Joined: 2004-10-11

This is not valuable thing at all.

Partial deployment - what is this? what is it good for? Are we supposed to be happy that our code can run without classes it uses? You really like playing such games?

Faster loading of classes - you must be kidding, dou you really think [i]this[/i] matters? Every class used in your project will sooner or later be loaded by the JVM. Exception can possibly be a class with constants only. But how many such classes is in your project? 1%? 0.001%?

Your example is good. At least we know there is workaround (i did not realized this would do it).

But from all we now know about this it is evident that current javac' behaviour makes more harm than good.

tsinger
Offline
Joined: 2003-06-10

Although your statement about the possible compiler problems is correct, I would vote against it, because I believe, the compiler should do as much as it can to speed-up the load at runtime. A lot of people (e.g. users of Java-desktop-applications) complain about the start-up-time. So why make it even slower? Wouldn't it be better to fix the compiler behaviour instead of the compiler output?

Tom

dgriffit
Offline
Joined: 2004-10-13

It's not just compilation, it's also deployment. If you depend on a public static final constant from a third-party library, and it changes between releases, your software will break unnecessarily, due to this (IMHO) premature optimization.

patrikbeno
Offline
Joined: 2004-10-11

good point. if you need to recompile class B just because value of the constant changed in class A, there's something wrong.

tsinger
Offline
Joined: 2003-06-10

If you compile/deploy your application, don't you make a full rebuild? I do, because I want to be absolutely sure, that everything is OK. Or didn't I understand you correctly?

Tom

vhi
Offline
Joined: 2004-10-11

Compilation is not always the case. Suppose you have implemented a component, version 1.0. Now, I am using the component in my application and I do not have a source code at hand. Now, you have fixed some bugs in your component, and the version is 1.01. Note that there are no 'interface' changes. Only implementational changes. I cannot put that in my application if you have changed your constants without recompiling my application. So, I have to contact my application vendor to provide me with a recompiled version. Now, the interface has not changed (the constant's name), but its implementation has changed. I do not think it that I should be forced to recompile my software for your implementation changes.

The problem exists in the component market, where it is necessary to mix and match different implementations for the same interfaces.

vhi
Offline
Joined: 2004-10-11

+1

patrikbeno
Offline
Joined: 2004-10-11

+1

monika_krug
Offline
Joined: 2004-10-14

Yes, this can cause really weird bugs. If this could be changed, it would be nice.

Monika.