Java for loop optimizations - java

What sort of optimizations would Java Runtime perform on the follow snippet of code? The bytecode doesn't reveal any optimization however I feel that Java should take the last value of the for loop without running the entire for loop since String is a rudimentary Java class.
NOTE. this question was asked on a class test; however, I couldn't provide enough evidence to back my claim.
public class Main {
public static void main(String[] args) {
String str = null;
for (long i = 0; i < 10000000000L; i++) {
str = new String("T");
}
System.out.println(str);
}
}

While I can't speak to exactly what the jit compiler is doing, the optimization you are asking it to do (to determine that it is safe to skip the loop body entirely) is actually extremely difficult to do, and so I highly doubt it it is done. This is true regardless of String being a "rudimentary Java class".
To understand better, first let's assume that instead of String, we are creating instances of an arbitrary class Foo. It would only be safe to skip the creation of all those Foo objects if we knew two things: that calling new Foo() didn't have any observable side effects; and that no references to Foo "escaped" the loop body.
An observable side effect would be something like setting the value of a static member (e.g. if the Foo class kept a static count of all the times Foo() had been called). An example of a reference escaping would be if the this variable inside of Foo() was passed somewhere else.
Note that it isn't enough to just look at Foo(), you need to look at Foo's superclass' constructor (and all the way up the chain to Object). And then you need to look at all the code that gets executed upon initialization of each of those objects. And then look at all the code that gets called by that code. That would be a tremendous amount of analysis to do "just-in-time".
public class Foo extends Bazz{
static int count = 0;
public Foo(){
// Implicit call to Bazz() has side effect
count++; // side effect
Bazz.onNewFoo(this); // reference escaping
}
Bazz bazz = new Bazz(); // side effect
{
Bazz.onNewBazz(this.bazz); // reference escaping
}
}
class Bazz{
static int count = 0;
static List<Foo> fooList = new LinkedList<>();
static List<Bazz> bazzList = new LinkedList<>();
static void onNewFoo(Foo foo){
fooList.add(foo);
}
static void onNewBazz(Bazz bazz){
bazzList.add(bazz);
}
public Bazz(){
count++;
}
}
You might think we should just let javac do this analysis and optimization for us. The problem with that is, that there is no way to guarantee that the version of Foo() that was on the classpath at compile-time will be the same as that which is on the classpath at run-time. (Which is a very valuable feature of Java - it allows me to move my application from Glassfish to Tomcat without recompiling). So we can't trust analysis done at compile-time.
Finally, realize that String is no different from Foo. We'd still need to run that analysis, and there is no way to do that analysis in advance (which I why I can upgrade my JRE without recompiling my apps)

Related

Modify list - stream approach

I want to modify list of already created objects in stream. I realized three approaches that may do that, but I not sure about their performance and possible downsize.
Return same object - not waste of time to creating new object, but object is mutable
Create new object - parameter is not modified, but for huge object creation is time consuming
Modify parameter - can only use ForEach, no parallel usage
Code below code with explaining comments.
public class Test {
public static void main(String[] args) {
//Already created objects
List<Foo> foos0 = Arrays.asList(new Foo("A"));
//However I need to apply some modification on them, that is dependent on themselves
//1. Returning same object
List<Foo> foos1 = foos0.stream().map(Test::modifyValueByReturningSameObject).collect(Collectors.toList());
//2. Creating new object
List<Foo> foos2 = foos0.stream().map(Test::modifyValueByCreatingNewObject).collect(Collectors.toList());
//3. Modifying param
foos0.stream().forEach(Test::modifyValueByModifyingParam);
}
//Lets imagine that all methods below are somehow dependent on param Foo
static Foo modifyValueByReturningSameObject(Foo foo) {
foo.setValue("fieldValueDependentOnParamFoo");
return foo;
}
static Foo modifyValueByCreatingNewObject(Foo foo) {
Foo newFoo = new Foo("fieldValueDependentOnParamFoo");
return newFoo;
}
static void modifyValueByModifyingParam(Foo foo) {
foo.setValue("fieldValueDependentOnParamFoo");
return;
}
}
public class Foo {
public String value;
public Foo(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
So the question is which is the most stream approach?
EDIT:
By stream approach I mean, that the most advantages in sense of performence.
EDIT2:
1. Which is functional approach?
2. Which is best in sense of performance?
The javadoc states that Streams should avoid side effects :
Side-effects in behavioral parameters to stream operations are, in general, discouraged, as they can often lead to unwitting violations of the statelessness requirement, as well as other thread-safety hazards.
So, you should prefer the solution where you create new objects instead of modifying existing ones.
The different aproaches will in your case most likely result in no difference regarding performance.
Reason: optimization. Java will not really create new classes and will use direct access to fields. It might(and will if analysis sugests it) even skip a whole chain of calls and replace it by a precalculated value. Java runtime even utilizes a profiler to optimize and find hotspots...
Also: Regarding performance it is in general(particular cases may differ) more important to create a simple structure and help the runtime to make the right assumptions.
So if you hide what you are doing in unesseary manual "optimization", that hides optimization posibilities(lots of branches/decisions, unnecessary pinning, chain of "unknown" methods ...) from the runtime you might end up with a slower result.
For clarity and sideffects(see also other answer) I rather use the version that creates new instances.

Reusing same Object variable to create multiple objects

Is it an alright practice to reuse the same variable to keep making new Object instances (like case 2)?
Some pseudo code:
//case 1:
class main {
List<Foo> bar = new ArrayList;
public static main(String[] args) {
Foo baz = new Foo(params);
Foo baz1 = new Foo(differentParams);
Foo baz2 = new Foo..
}
}
class Foo {
Foo(params..) {
main.bar.add(this);
}
}
//case 2:
class main {
List<Foo> bar = new ArrayList;
public static main(String[] args) {
Foo baz = new Foo(params);
baz = new Foo(differentParams);
baz = new Foo..
}
}
class Foo {
Foo(params..) {
main.bar.add(this);
}
}
I am wondering if case 2 is an okay design practice. Since in Foo I am storing the instance of the class in the list in main, I will never need the direct object variable baz1 during runtime, but will be iterating through the list to apply some logic to each object.
So my question is, is it an alright practice to reuse the same variable to keep making new Object instances (like case 2)? Conventional practices would suggest to keep a separate variable for the objects as you make them (like case 1).
This question came up in my mind when thinking about memory and whether or not doing case 2 would save more memory compared to case 1 since you are not declaring a new variable each time.
This question came up in my mind when thinking about memory and whether or not doing case 2 would save more memory compared to case 1 since you are not declaring a new variable each time.
On Android, the memory is severely limited, IIRC an app can use only 20 MB. One variable may take 4 bytes, and you save two variables, i.e., 8 bytes. This means that when you write 250,000 such classes, you save 2 MB, i.e., 10% of available memory.
Are you going to write a quarter million of such classes?
I hope, you are not.
But then, it doesn't matter as local variables exist only when the method is called and nobody cares about 8 bytes.
Moreover, your code gets processed by an optimizing compiler, which doesn't transform your code line by line. So it's possible, that there's no difference in the generated code for your two versions.
So please, don't try optimizing irrelevant details.
Write proper code instead. As you've been said, "a constructor shouldn't have side effects, and shouldn't escape this".
I'd suggest something like this:
class Main { // class names are always UpperCamelCase
private List<Foo> bar = new ArrayList; // "private"
public static main(String[] args) {
new Main().go(); // leave the static context ASAP
}
private void go() {
bar.add(new Foo(params));
bar.add(new Foo(differentParams));
bar.add(new Foo(....));
}
}
No magic there. The constructor constructs and does nothing else.
Everything gets added explicitly... this may get verbose, but then you'd just write a method encapsulation common operations.

ExecutorService taking a runnable which is still under construction

I would like to know if this piece of code is correct or not. Will this not lead to issues as I am submitting the runnable object to the executor service while constructing the object itself?
public class A implements Runnable {
public A() {
Executors.newSingleThreadExecutor().execute(this);
// some other initializations
}
}
Will this lead to any issues as we are trying to submit the object to the executor even before creating it completely? If the run() method is called even before all the initializing is done (if at all it's possible), will the variables still be null which were not yet initialized?
Please do not ask me to come up with the complete code, as I have been asking this as a general question which requires clarification.
Yes, there may be issues. The Executor might read a field that you set in the constructor, even before the corresponding code in the constructor was executed. In general you should not expose this from inside a constructor. Java provides useful guarantees for objects after their constructor finished, but in order to benefit from those you have to wait for the result of new X(...) before using it.
Will this lead to any issues as we are trying to submit the object to
the executor even before creating it completely?
For one thing, you can get final variable that are still changing value - that is quite bad per the semantics of final. It can lead to very hard-to-trace concurrency bugs in multi-threaded code.
This code will usually print a few zeros and even the occasional 4, even though the final field a is only ever assigned the value 4 and should never been seen having any other value than 4.
public class A implements Runnable {
private static ExecutorService threads = Executors.newSingleThreadExecutor();
final int a;
public A() {
threads.execute(this);
Thread.yield();
a = 4;
}
#Override
public void run() {
if (a != 4) {
System.out.println(a);
}
}
public static void main(String[] args) {
for (int i = 0; i < 50_000; i++) {
new A();
}
threads.shutdown();
}
}
If the run() method is called even before all the initializing is done
(if at all it's possible), will the variables still be null which were
not yet initialized?
Yes, the ones not yet initialized will be null for reference variables, or the default value (0, false, '\0', 0d, 0f, etc.) for the primitive types. It is even possible according to the specifications with long and double fields to see only 32 of the 64 bits initialized (although on 64 bit architectures it is unlikely that you will ever observe this)
There will almost certainly be issues. What you have is called a "this escape" where you pass a this reference in a ctor to an external method. It's super bad, the object is incompletely constructed at that point and anything could happen.
What you should probably do instead is make the constructor private and use a factory method to get a new instance and execute it, if that's the goal.
public class A implements Runnable {
public A getNew() {
A a = new A();
Executors.newSingleThreadExecutor().execute(a);
return a;
}
private A() {
// some other initializations
}
}

Java Compile Time error for instance level Final variables and not giving for method level local variables [duplicate]

This question already has answers here:
Why Final variable doesn't require initialization in main method in java?
(4 answers)
Closed 5 years ago.
Why is the java compiler not giving any compile time error for method level local final variables when we not initialize them?
( but it is giving en error for instance level final variables when they are not initialized ).
public class FinalKeyword
{
final int j; // error: the blank final field j may not have been initialized.
public static void main(String[] args)
{
final int k; // not giving any Compile time error!
}
}
Thing is: as soon as you change your main() method to
final int k;//Not Giving any Compile time error
System.out.println(k); //different story now!
You get an error about k not being initialized, too!
The point is:
the compiler has to make sure that other source code that isn't visible right now ... is able to do a new FinalKeyword() without problems. Thus it can't allow you to keep j not initialized.
but that main() method ... even when another method invokes this main() method - that is fine. The method does nothing! In other words - it is not a problem to define a variable that doesn't get used within a method! Because there is no way how you could get to that variable!
The compiler has to prevent you from getting into situations where you "stumble" over an uninitialized variable. When you invoke a method that has such variables ... but never uses them - that is simply a "don't care".
And surprise: when we go with
public class FinalTest {
public static void main(String args[]) {
final int k;
}
}
and compile that; and then we use javap to get to de-compiled byte code:
public static void main(java.lang.String[]);
Code:
0: return
This is one of the rare occasions where javac does a bit of optimization - by simply throwing away unused variables. Bonus fun fact: even when changing my example to k=5; - you will find that the class file still only contains return!
j is a field of the class. k is not. You need to initialise final fields in the class's constructor. Your class is using your default, implicit constructor which does no initialisation of fields.
The reason it doesn't give you a warning for the local variable is because you don't use it. If you were to use the uninitialised local variable, you would get an error:
public static void main(String[] args)
{
final int k;
if (k < 5) {
// whatever
}
}
As to why the compiler's not clever enough to know that you're not using the field either, I'm not sure. It's presumably more complex because of inheritance, access levels and such.
In general, if the compiler comes across a situation where a final may be accessed while uninitialized, or set while initialized, there is an error.
A class's final fields must be initialized, because someone could access them at any time. If it is package-private, protected, or public, other code can directly access the field, and they expect it to be initialized. Even if the field is private, someone could reflect it and try to access it, so the compiler must not ignore it.
A method's final locals are internal to the method, and there is no way to reflect inside a method without modifying some bytecode, so the compiler does not need to be so strict. Instead, the compiler does control flow analysis to map out when the field will be assigned and won't be assigned, and it will throw an error if it is used while maybe unassigned, and will be content if it is never used or is used while definitely assigned.
void meth0() {
final String s;
// Compiler: s is never used; I don't care.
}
void meth1() {
final String s;
// s is definitely unassigned
if(something()) {
s = "something";
// s is definitely assigned
System.out.println(s);
} else {
// s is definitely unassigned
s = "other";
// s is definitely assigned
System.out.println(s);
}
// if-branch def. assigns s, else-branch def. assigns s
// Ergo: s is def. assigned
somethingElse(s);
// Compiler: control flow checks out; code is valid
}
void meth2() {
final String s;
// def. unass.
if(something()) {
s = "something";
// def ass.
}
// s is in undetermined state
// s = ""; // s may be assigned; error
// use(s); // s may not be assigned; error
// s is now totally unusable. Nice job breaking it, hero!
}

Java: Static initialization

can you explain me which is the difference between:
public class Test {
public static final Person p;
static {
p = new Person();
p.setName("Josh");
}
}
and
public class Test {
public static final Person p = initPerson();
private static Person initPerson() {
Person p = new Person();
p.setName("Josh");
return p;
}
}
I have always used the second one, but is there any difference with an static initializer block?
There are of course technical differences (you could invoke the static method multiple times within your class if you wanted, you could invoke it via reflection, etc) but, assuming you don't do any of that trickery, you're right -- the two approaches are effectively identical.
I also prefer the method-based approach, since it gives a nice name to the block of code. But it's almost entirely a stylistic approach.
As Marko points out, the method-based approach also serves to separate the two concerns of creating the Person, and assigning it to the static variable. With the static block, those two things are combined, which can hurt readability if the block is non-trivial. But with the method approach, the method is responsible solely for creating the object, and the static variable's initializion is responsible solely for taking that method's result and assigning it to the variable.
Taking this a bit further: if I have two static fields, and one depends on the other, then I'll declare two methods, and have the second method take the first variable as an explicit argument. I like to keep my static initialization methods entirely free of state, which makes it much easier to reason about which one should happen when (and what variables it assumes have already been created).
So, something like:
public class Test {
public static final Person p = initPerson();
public static final String pAddress = lookupAddress(p);
/* implementations of initPerson and lookupAddress omitted */
}
It's very clear from looking at that, that (a) you don't need pAddress to initialize p, and (b) you do need p to initialize lookupAddress. In fact, the compiler would give you a compilation error ("illegal forward reference") if you tried them in reverse order and your static fields were non-final:
public static String pAddress = lookupAddress(p); // ERROR
public static Person p = initPerson();
You would lose that clarity and safety with static blocks. This compiles just fine:
static {
pAddress = p.findAddressSomehow();
p = new Person();
}
... but it'll fail at run time, since at p.findAddressSomehow(), p has its default value of null.
A static method (second example) is executed every time you call it. A static init block (first example) is only called once on initializing the class.
http://docs.oracle.com/javase/tutorial/java/javaOO/initial.html
The advantage of private static methods is that they can be reused later if you need to reinitialize the class variable.
This does not count for final instances, because a final variable can only be initialized once.
initPerson requires calling at some point, whereas the static block is executed when creating the Test object.
The static before a function specifies that you can use that function by calling it on the Class name handle itself. For example, if you want to create a Person object outside the class you can write
Person p = Test.initPerson();
However, there is no advantageous difference between the two as you can access the object p outside the class in both cases.

Categories

Resources