I Have three classes
StaticHolder.java - Which holds a static variable.
StaticInitializer.java -Responsible only for initializing the variable through a static method.
Application.java - Retrieves the static variables value through getter method.
I thought initializing a static variable once in JVM will not go until we stop the JVM. So I called ran StaticInitializer once which will do the initialization. And tired to access its value from another class which is not working and returning null. Can anyone explain why. Thanks In Advance.
public class StaticHolder {
private static String hello;
public static void ini() {
hello = "Hello World";
}
public static String getHello() {
return hello;
}
public static void setHello(String hello) {
StaticHolder.hello = hello;
}
}
class StaticInitializer {
public static void main(String[] args) {
StaticHolder.ini();
while (true) {
Thread.sleep(1000);
}
}
}
public class Application {
public static void main(String[] args) {
System.out.println(StaticHolder.getHello());
}
}
static does not mean that this value is there forever!
It is only theree for the current java session.
Invocing the java command at the command line starts a new java session where the value needs to be initialized again.
Actually I have a daemon thread which does the initialization and stays alive.And I have another stand alone java program which tries to get the value.
Without knowing that other code involved my gueass is that you did not establish inter process communication.
The easiest way it that you "deamon" opens a server socket and your "stand alone java program" connects to it an queries the desired data through it.
So there is only one main method that can be executed as entry point for the entire application for each JVM run.
When the JVM is executed you can specify which class has to be loaded at start. The Classloader take care to load that class and then the JVM can execute the only one public static void main(String[] args) method.
In Java you need to have at least one class with a public static method named main. I suggest to read this post to understand why it is public static.
The Java Classloader is a part of the Java Runtime Environment that
dynamically loads Java classes into the Java Virtual Machine.
Usually classes are only loaded on demand.
So returning to your question, given that when Application.main is running there is no way to execute StaticHolder.init(), I suggest to change your main in this way:
public class Application {
public static void main(String[] args) {
StaticHolder.init();
System.out.println(StaticHolder.getHello());
}
}
or change StaticHolder in this way and remove the init:
public class StaticHolder {
private static String hello;
static {
hello = "Hello World";
}
public static String getHello() {
return hello;
}
public static void setHello(String hello) {
StaticHolder.hello = hello;
}
}
On the other hand, just to be clear if you run the StaticInitializer.main this has no effect on Application.main execution.
In your program , when main method of StaticInitializer is first executed, a String named hello is initalized. and as ini() method is called, the value 'Hello world' is assigned to hello. Then jvm exists main method, and then stops working. Again when we compile application class,instead of the previous hello variable , a new hello string variable is created with no value assigned(null valued) . That's why you're getting null as output. Thankyou.
Related
I've included my code below. Following some other examples, I even tried to dynamically load the class in order to force it to run the static block, but that doesn't solve my problem. The class is loaded and class.getName() is printed successfully, but still, when it gets to the last line in the main method it throws an error saying the array is null.
All the other answers address things which don't seem to apply here, like how using the "final" keyword can allow the compiler to skip static blocks. Any help is appreciated!
package helper;
public class StaticTest {
public static boolean [] ALL_TRUE;
private static void setArray(){
ALL_TRUE = new boolean[8];
for(int i=0;i<ALL_TRUE.length;i++){
ALL_TRUE[i] = true;
}
}
static {
setArray();
}
public static void main(String [] args){
ClassLoader cLoader = StaticTest.class.getClassLoader();
try{
Class aClass = cLoader.loadClass("helper.StaticTest");
System.out.println("aClass.getName() = " + aClass.getName());
} catch(ClassNotFoundException e){
e.printStackTrace(System.out);
}
System.out.println(StaticTest.ALL_TRUE[0]);
}
}
In case anyone else lands here, the problem was that I had checked the Netbeans option "Compile on Save" (under Build->Compiling). Somehow, compiling files immediately upon saving was preventing the static block from being run.
Again, thanks to everyone who chimed in to verify that the code itself worked as expected.
I'm developing an application that requires two main() classes, first one for the actual application, and a second one for the JMX connectivity and management. The issue I'm facing is even after ensuring the first main() is executed and initializes the variables, when the second main() runs but does not see those variables and throws null exception.
Application main():
public class GatewayCore {
private static Logger logger = Logger.getLogger(GatewayCore.class);
private static ThreadedSocketInitiator threadedSocketInitiator;**
private static boolean keepAlive = true;
//private static Thread mqConnectionManager;
public static void main(String args[]) throws Exception {
__init_system();
__init_jmx();
__init_mq();
while(keepAlive) {}
}
private static void __init_system() {
try {
logger.debug("__init_system:: loading configuration file 'sessionSettings.txt'");
SessionSettings sessionSettings = new SessionSettings(new FileInputStream("sessionSettings.txt"));
logger.info("\n" + sessionSettings);
MessageStoreFactory messageStoreFactory = new FileStoreFactory(sessionSettings);
LogFactory logFactory = new FileLogFactory(sessionSettings);
MessageFactory messageFactory = new DefaultMessageFactory();
Application sessionManager = new SessionManager();
threadedSocketInitiator = new ThreadedSocketInitiator(sessionManager, messageStoreFactory, sessionSettings, logFactory, messageFactory);
...
public static ThreadedSocketInitiator getThreadedSocketInitiator() {
return threadedSocketInitiator; }
Secondary main() class, meant to be invoked for JMX-Mbean purpose:
public class RemoteCommandLine {
private static Logger logger = Logger.getLogger(RemoteCommandLine.class);
private static final String JMX_SERVICE_URL_PREFIX = "service:jmx:rmi:///jndi/rmi://";
private static final String HOST = "localhost";
private static String PORT = "24365";
private static JMXConnectionInstance jmxConnectionInstance;
private static boolean keepAlive = true;
public static void main(String[] args) throws IOException, MalformedObjectNameException, ConfigError {
logger.debug(GatewayCore.getThreadedSocketInitiator());
...
From command line, I first run:
java -classpath etdfix.jar:slf4j-api-1.7.25.jar:mina-core-2.0.16.jar:quickfixj-all-2.0.0.jar -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=24365 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false com.scb.etdfix.GatewayCore sessionSettings.txt
Wait for the inits to complete, ensuring threadedSocketInitiator has been assigned, then:
java -classpath etdfix.jar:slf4j-api-1.7.25.jar:mina-core-2.0.16.jar:quickfixj-all-2.0.0.jar com.scb.etdfix.JMX.RemoteCommandLine
Which ultimately throws a null pointer exception for the line:
logger.debug(GatewayCore.getThreadedSocketInitiator());
My plan is to have the first main() initialize the object, then pass to the second main() to do further method calls using the same object (it must be the same instance) when it is manually invoked. Both classes are compiled together into the same JAR. Please advise on how I can get around this issue or anything I can do to debug this further.
In fact, I'm thinking that this may not be possible as when the 2nd main() is invoked, from its POV the first main() isn't initialized. Therefore I should approach this by considering that they are two separate entities.
Each process (each java command) is completely separate, whether they run the same main() or not. This is a feature—the alternative would be to have unrelated parts of the system collide whenever they used a common utility.
That said, nothing stops you from calling GatewayCore.main() yourself (with the real command line or whatever other argument list) if you want to reuse its logic. It might be a good idea, though, to factor out the common code as another function: main() has many special responsibilities and programmers do not usually expect it to be called within a program.
I have a class Normal with the following code:
public class Normal {
private static String myStr = "Not working...";
private static boolean running = true;
public static void main(String[] args) {
while(running) {
System.out.println(myStr);
}
}
}
And I have another class named Injector in another project. Its purpose is to change the values of Normal even though they are not in the same JVM:
public class Injector {
public static void main(String[] args) {
String PID = //Gets PID, which works fine
VirtualMachine vm = VirtualMachine.attach(PID);
/*
Set/Get field values for classes in vm?
*/
}
}
What I want to do is change the values myStr and running in the class Normal to "Working!" and false respectively without changing the code in Normal (Only in Injector).
Thanks in advance
You'll need two JARs:
One is Java Agent that uses Reflection to change the field value. Java Agent's main class should have agentmain entry point.
public static void agentmain(String args, Instrumentation instr) throws Exception {
Class normalClass = Class.forName("Normal");
Field myStrField = normalClass.getDeclaredField("myStr");
myStrField.setAccessible(true);
myStrField.set(null, "Working!");
}
You'll have to add MANIFEST.MF with Agent-Class attribute and pack the agent into a jar file.
The second one is a utility that uses Dynamic Attach to inject the agent jar into the running VM. Let pid be the target Java process ID.
import com.sun.tools.attach.VirtualMachine;
...
VirtualMachine vm = VirtualMachine.attach(pid);
try {
vm.loadAgent(agentJarPath, "");
} finally {
vm.detach();
}
A bit more details in the article.
I am getting a strange error while creating a simple thread program in JAVA using Eclipse. The code is:
package threadshow;
public class Thread_Show extends Thread{
public void run(){
System.out.println("Inside the thread");
}
}
class Thread_Definition{
Thread_Show ts=new Thread_Show();
ts.start(); //Getting the error here
}
I am getting error "syntax error on token start identifier expected" in the line ts.start();. Why am I getting this?
EDIT I have used the code from http://tutorials.jenkov.com/java-concurrency/creating-and-starting-threads.html#thread-subclass
Found a very bad mistake done my me. Forgot to add public static void main(String args[]) in the Thread_Definition class.
You can't start your method inside class. Create some method first.
Are you defining both of your classes in the same java file?. If so, you define both the classes in different java files naming Thread_show and Thread_definition. Then inside Thread_definition you can create an object of Thread_show and call its function.
ADD main method-public static void main(String[] args)
package threadshow;
public class Thread_Show extends Thread
{
public void run()
{
System.out.println("Inside the thread");
}
}
class Thread_Definition
{
public static void main(String[] args)
{
Thread_Show ts=new Thread_Show();
ts.start();
}
}
I have written simple java program:
package bsh;
import test.Testclass;
public class Whatever {
public static void main(String args[]){
Testclass t = new Testclass();
System.out.println(t.squareIt(8));
}
}
package test;
public class Testclass {
public Testclass(){
}
public int squareIt(int i){
return i*i;
}
}
I have two questions about this java program:
How to execute this java program from jmeter?
How to call sqaureIt(int i) method from jmeter?
How can i achieve this?
I haven't tried main class execution , but i have certainly executed Junit Testcases through Jmeter
Have a look at this doc Junitsampler tutorial
Aside from following the tutorial as Sudhakar mentioned...
Your main test case must extend TestCase or some form of it. Your test method must begin with the word test or use annotations.
Do not use a void main method as in a normal java application.
It will automatically call and run your method that starts with the name test.
So you could do this:
public class Whatever extends TestCase {
public void testIt() {
//test code here
new Testclass().squareIt(5);
}
}
JMeter is typically used for testing performance on web applications. Correct me if I'm wrong, but unless you plan on converting this into some sort of web app, you should try using VisualVM to measure your program's performance.