Maybe it is time here to quote Arthur Clarke's 3rd law :
"Any sufficiently advanced technology is indistinguishable from magic"
(See : https://en.wikipedia.org/wiki/Clarke%27s_three_laws)
The process by which Tomcat is started and/or stopped - particularly under Windows and as
a Service - is not very clear in the on-line documentation.
Neither is it it very easy to write a comprehensive and accurate documentation, because
the thing has gotten to a point where, for mere mortals, it is really quite complicated.
(Have a look at bin/catalina.bat to get an idea).
So let me give you some overall pointers (some of them quite basic, I apologise), and
maybe in there somewhere, you'll find wat you are missing to complete the picture and do
what you want to do.
1) Tomcat is a compiled java application, in java bytecode. To run this bytecode, you
need a JVM. The JVM is machine-executable code, so to run tomcat, you run a JVM and tell
it to run the tomcat bytecode.
2) the java JVM for Windows is not very good at running as a Windows Service (it does not
handle the appropriate Windows "signals" etc.). To solve this, when you want to run tomcat
as a Windows Service (or rather - see above - run the JVM as a Windows Service), you
actually run a specialised "wrapper program" which does work well as a Windows Service,
and you ask this wrapper to start the JVM which runs tomcat.
To make matters a bit more confusing (or maybe, for some, clearer), this generic "Windows
Service JVM wrapper" is renamed to "tomcatV.exe" (where V is the tomcat version, so for
tomcat 9, the program is called tomcat9.exe).
3) the wrapper program, when it starts the JVM, has to know which command-line switches it
should pass to it. For the Windows Service flavor of tomcat, these parameters are stored
in a number of special keys in the Windows Registry, and that is where the wrapper picks
them up, before starting the JVM.
4) To make it easier to set and edit these JVM command-line parameters, tomcat provides
another Windows executable program - a specialised GUI Registry Editor - which is also
renamed according to the tomcat version, as tomcatVw.exe (where V is the tomcat version,
so for tomcat 9 it would be tomcat9w.exe).
5) as a separate bit of knowledge, I would suppose that everyone knows that on any given
host, a given TCP listening port can only be opened by one process at a time. If a second
process tries to open a port which is already opened by a first process, it will get an
error of the kind "port already in use", and most probably the second process will then
exit (non-gracefully).
6) in the tomcat conf/server.xml file, there is a tag :
<Server port="8005" shutdown="SHUTDOWN">
This provides a clue as to how one actually *stops* tomcat : one opens a TCP connection to
locahost port 8005 (on which tomcat listens), then sends the string "SHUTDOWN" on that
connection. This causes tomcat to shutdown gracefully, at the end of which it does a
"system.exit()" which shuts down the JVM that runs it.
And this in turn causes the JVM wrapper program to tell Windows that the tomcat Service is
shutting down, before itself exiting. And thus is all well and tidy in the Windows Service
world.
7) a helpful feature of tomcat, is that it itself provides code to connect to localhost
port 8005 and send that shutdown string, so that one does not have to write its own
separate program to do that.
The bit that is a bit confusing about this feature however, is that in order to use that
code, one of course needs to start up another separate instance of tomcat, just to run
that code and actually stop the "real" running tomcat.
And of course running a separate instance of tomcat actually means running a separate
instance of the JVM which runs tomcat.
Now armed with all the above knowledge, and with the dialog window offered by the
tomcat9w.exe program, it is relatively easy to figure out what happens (or at least what
may happen in your case, in my modest non-java-expert opinion).
Looking only at the last 3 tabs of that window (Java / Startup / Shutdown), one can figure
out that :
- the "java" tab contains the path of the JVM to be started, and the command-line
parameters that will be passed to that JVM
- the "Startup" tab contains the java class that the JVM should invoke at the start of
tomcat, and the argument ("start") to pass into that initial call.
- the "Shutdown" tab contains the java class that the JVM should invoke to stop an
already-running tomcat, and the argument ("stop") to pass into that initial call.
(Thus triggering the code in (7) above).
And I believe that, in the particular case of Tomcat being run as a Windows Service, here
may be the origin of the problem which you are encountering : the "Java" tab lists
command-line options that are *common* to both the JVM which starts tomcat, and to the
(separate) JVM which stops tomcat. There is only one set of JVM options, for both cases.
Which means that if, in these JVM command-line options, you pass it one that tells the JVM
to open some extra listening port (which you do to enable JMX), then this will happen both
when a JVM is started because tomcat is being started, and when a JVM is started because
tomcat is being stopped.
And of course the second one will fail, because the first one has already
opened that port.
(Note that this will happen no matter which level of indirection you build into the
Registry JVM parameters.)
Why does that happen only with that JMX port, and not with the other listening ports that
tomcat opens ?
Well, that is a question of /when/ these different things happen : the JMX-port
command-line parameter "happens" earlier, because it is something that the JVM does,
before it evens starts running tomcat bytecode.
While the other ports that Tomcat opens, happen in the code of tomcat itself, when it is
being run. And that tomcat code is smart enough to know that when it is being run with the
argument "stop", then it should not open these other ports mentioned in its configuration
file.
On the face of it, it seems a bit of an unsolvable issue, unless the tomcat Service
wrapper code is changed, to allow for 2 separate sets of JVM parameters (one for start,
with the JMX options; and one for stop, without these options).
Or unless something is done in the Tomcat code itself, to allow JMX to be started (or not)
from within Tomcat (assuming that's even possible).
Of course, one could also wonder if you really need JMX when you run tomcat in production
mode. If this is only for testing, you could run tomcat in a console, where you would not
have the same issue (because you would not have the wrapper with its single-minded preset
JVM options).
(Or you could switch to Linux ;-))
On 09.08.2018 02:06, Daniel Savard wrote:
Le mer. 8 août 2018 à 12:08, Louis Zipes <louis.zi...@gmcr.com> a écrit :
Hi Calder,
I can successfully start up as a Windows service and get JMX working BUT
my problem is that Service doesn't stop cleanly (just repeating that
problem in case it wasn't made clear). It says the PORT is already in use
which led me to try to use Catalina_Opts as per the suggestions on the
internet.
Port already in use: 8008; nested exception is:
java.net.BindException: Address already in use: JVM_Bind
If you were able to get JMX working and you can start AND stop the Tomcat
service cleanly, do you mind sharing me your 'scrubbed' Java tab contents
as I can seem to get the right combination to get it to Start and Stop the
service.
Thanks, Louis
Louis,
I believe you need to understand a bit more how things are working with
Java and the JVM. The -D options are pretty straight forward for anyone
knowing how you define properties to the JVM on the command line. I already
told you everything you need to know to setup properly your Tomcat. Since
you were the one talking about CATALINA_OPTS I assumed you did know where
and how to setup the variable for your installation. Otherwise, just go in
the setup utility for Tomcat on Windows and put the
-Dcom.sun.management.conf.file=${catalina.base}/conf/abc.def entry there
without the CATALINA_OPTS= stanza since this one's intent is to set an
environment variable for the process to pick while the former is passing
directly the property to the JVM from the Tomcat Windows Setup dialog.
There is many ways to do things. Bottom line, you need to tell the JVM
where is the configuration file for JMX and put your properties in there as
any other properties file. This is standard stuff.
The effect is the JVM now knows your port is a JMX port and it will stop to
try to use it when it is already in use and free it cleanly.
Regards,
-----------------
Daniel Savard
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org