Description
Investigative information
Repro steps
Provide the steps required to reproduce the problem:
- Create Function.java below.
package com.azure.yutobo.func;
import com.microsoft.azure.functions.ExecutionContext;
import com.microsoft.azure.functions.HttpMethod;
import com.microsoft.azure.functions.HttpRequestMessage;
import com.microsoft.azure.functions.HttpResponseMessage;
import com.microsoft.azure.functions.HttpStatus;
import com.microsoft.azure.functions.annotation.AuthorizationLevel;
import com.microsoft.azure.functions.annotation.FunctionName;
import com.microsoft.azure.functions.annotation.HttpTrigger;
import java.util.Optional;
public class Function {
static final Person person = new Person();
@FunctionName("foo")
public HttpResponseMessage foo(
@HttpTrigger(
name = "req",
methods = {HttpMethod.GET, HttpMethod.POST},
authLevel = AuthorizationLevel.ANONYMOUS)
HttpRequestMessage<Optional<String>> request,
final ExecutionContext context) {
context.getLogger().info("foo processed a request.");
return request.createResponseBuilder(HttpStatus.OK).body("Foo: " + person.).build();
}
@FunctionName("bar")
public HttpResponseMessage bar(
@HttpTrigger(
name = "req",
methods = {HttpMethod.GET, HttpMethod.POST},
authLevel = AuthorizationLevel.ANONYMOUS)
HttpRequestMessage<Optional<String>> request,
final ExecutionContext context) {
context.getLogger().info("bar processed a request.");
return request.createResponseBuilder(HttpStatus.OK).body("Bar: " + person).build();
}
}
package com.azure.yutobo.func;
class Person {
String name = "";
int age = 18;
Person() {}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
@Override
public String toString() {
return "Person [age=" + age + ", name=" + name + "]";
}
}
- access Foo & Bar endpoints.
Expected behavior
Foo & Bar methods show the same output because they share the same class variable.
Actual behavior
Foo & Bar methods show the different output like below.
I found that there are separate class variables of Function.class in the heap.
And, Function.class loaded twince by the different URLClassLoader.
Apparently, you don't check whether Function.class is already loaded or not.
Known workarounds
I couldn't find workarounds.
Impact
- There appears to be no ways to share the class variable even methods are in the same class.
- I think we can't make Double-checked locked instance to get Singleton in multi-thread environment.