Java Notes
Last change May 21, 2005 AD
Index
- Notes
- notes for which I haven't found any other
place :-)
- packages & directories: friend and
enemy
- APIs (Application Programming interfaces) and other
- Other (utilities, non Sun APIs ...)
- Tools etc.
- jdb - debugger
- JAR archives
- JavaDoc comments
- Security and policytool
- GCJ - Java to native code GNU Java Compiler
(+libraries, Java interpreter etc.)
- NetBeans IDE
- Links you can need
Notes
- Destructor: Java hasn't anything like that. You can
write your clean-up code in the method
void finalize() and
somewhere in the beginning of your code write
System.runFinalizersOnExit(true); to ensure it will be
called. But runFinalizersOnExit is deprecated for it's
unsafe (in multithreaded program?). See Java
API documentation.
- javadoc: if you have an interface class (1 file) and
its implementation class (2nd file), you can compile them either together
or first the interface and then the implementation.
Packages
To make your source file to be part of a package, type in the source
"package package_name;".
Packages & Directories
It may be a bit confusing, when you start using packages. Suppose we
have directory java/mypackage and our source files, that form the
package 'mypackage', are in this directory:
This is our file/directory structure:
java> ls
mypackage
java> ls mypackage
MyInterf.java
MyImpl.java
Compile .java source by javac:
java/mypackage> javac MyInterf.java MyImpl.java
Compile .class source by rmic (assume we want to use RMI) -
notice we are in java/ and we don't mention the extension:
java> rmic mypackage.MyImpl
And, finally, let's run it by java (if we indeed use RMI, we have
to run rmiregistry first) - notice we are in java/ and we don't
mention the extension:
java> java mypackage.MyImpl
Packages revisited
It can be even more tricky, if you have your code spread over more
packages. Assume we have the following directory (and file) structure:
home
|- worm
|- net
| |- Network.java
|
|- chat
|-
ChatMessage.java
Our main package is "worm" and it contains two sub-packages: "net" and
"chat". The directory "worm" is in our home directory.
That's why we have the following:
In ChatMessage.java there is : "package
worm.chat;"
In Network.java there is the line : "package
worm.net;"
Assume also, that the source Network.java uses the class ChatMessage. For
that purpose, we add one more line into our source:
In Network.java there is the line: "import
worm.chat.ChatMessage;"
Now, how do we compile it? We go to the home directory, FIRST compile
ChatMessage.java and then Network.java, which depends on ChatMessage.java .
See:
Ex (the compiler's output not shown):
home> ls
worm
home> javac worm/chat/ChatMessage.java
home> javac worm/net/Network.java
Security
- run "policytool" to create/change a policy file (see this article-
also about cryptography and security in general, in Java)
- the policy file for your application is in the java.security.policy system
property
- if you run a program and set policy to a non-existing file, java won't tell
you it can't find the file, so you may believe everything is OK, until
something doesn't work because it hasn't the permission it
needs (I guess that if java doesn't find the policy file, it uses the default
one)
Granting permission (copied from the article mentioned above):
***
When granting permissions, you can base them on who signed
the code, where the code came from (the codebase), or grant them to everyone.
The java.security.Permission class serves as the base
class of all 1.2 permission-related classes. What an actual grant statement
looks like in the policy file follows. This would allow
write access to the local temporary directory, and all subdirectories
recursively, for code
signed by JavaJoe and downloaded from
http://www.TrustedUserHome.foo. If an asterisks (*) was used instead of a
dash (-), the
permissions would be for only the specific directory, not
its subdirectories, also.
grant signedBy "JavaJoe", codeBase
"http://www.TrustedUserHome.foo" {
permission java.io.FilePermission "c:\\temp\-";
}
***
For checking the current permissions, you can use
AccessController.checkPermission (Permission perm) - if the permission is not
granted, it throws the
AccessControlException that is a subclass the SecurityException. "perm" is
obtained by a constructor (which takes, e.g., an object and the operation
that shall be performed as
parameters). (System does the checking for permissions by itself, except for
your own defined perm.).
Networking
Networking Notes
- get IP address of your computer:
java.net.InetAddress.getLocalHost(); returns InetAddress (when printed,
it's HostName/HostAddress). You can use InetAddress's methods
.getHostName() and .getHostAddress() to get the name/IP
(both return String). See javadoc for InetAddress.
RMI 1 - notes
Note: 'remote object' is also called 'remote service' (for it indeed provides
a service to the callers) (and 'service' is wide used, e.g. for rmiregistry)
Terminology:
- host - the machine running the remote object (and rmiregistry)
- client - the program asking to use a remote object (service)
Notes:
- Naming&lookup: usually they say the address should be "http://...",
but in 1 article there was "rmi://..."
- http or ftp server must be running, as a class file provider (unless
the client has the necessary .class files (stub) on its classpath) (see
also RMIClassLoader)
- rmiregistry must be started from the directory including the .class
files (otherwise it won't find your stubs), unless you set correctly the
codebase property (assume your stubs are in the 69/ directory on the
local disc and aren't in any package):
$> java -Djava.rmi.server.codebase=file:/home/YAK/69/
MyRMIServiceProgram
- both client and server must have the interface def. (and stub, if you
don't won't to bother with downloading them) files before they start to
communicate
- if you run the server&client locally, from the same directory,
you don't need to use security manager and policy file.
- codebase and downloading stubs
(observations by one developer)
Registry
- See Registry
interface (Sun), java.rmi.registry.LocateRegistry
(Sun; among others has methods to run rmiregistry [createRegistry],
obtain a reference to a remote registry [getRegidtry]).
- Starting rmiregistry from within the program, if not yet started:
import java.rmi.registry.*; import java.rmi.RemoteException;
try {
LocateRegistry.createRegistry( Registry.REGISTRY_PORT );
} catch ( java.rmi.server.ExportException exex ){
if( exex.detail instanceof java.net.BindException){
// do nothing, registry already running
} else {
// this is an error, should be solved somehow
}//if-else is BindException
} catch ( RemoteException remi ){
// this is an error, should be solved somehow
}//try-catch get registry
- set the codebase (it can throw SecurityException; the protocol and
the trailing slash are very important):
// protocol + current directory (of the VM) + trailing slash
String codebase = "file:"+System.getProperty("user.dir")+"/";
System.setProperty( "java.rmi.server.codebase", codebase );
Remote Class Loading
See RMIClassLoader.
Used for example if the client is an applet (a browser needs to download the
applet and all the other classes)
- via http/ftp server (=> must be running)
- certain properties must be set when the JVM (=>application) is run
(form is: $> java [ -D<PropertyName>=<PropertyValue>
]+<ClassFile>)
- java.rmi.server.codebase is an URL and specifies where are the supplies
classes for objects sent out of that machine (either http:, ftp: or
file:)
- ? both rmi client and rmi server need a SecurityManager (or at least
one of them)
Errors (Exceptions):
1.Connection refused
a) when running the client:
java.rmi.ConnectException: Connection refused to host:
130.236.230.140; nested exception is:
java.net.ConnectException: Connection refused
This may mean that the server class or rmiregistry is not running (by
'server class' I mean the class which creates&binds the remote interface
implementation, in its main() method.
b) when running the server:
- the same output as above, only instead of the IP number you will see
'localhost'
In this case it's likely that rmiregistry is not running.
RMI 2 - complete example
(source: Java for Practitioners, John Hunt)
Part 1 - server
To use RMI do:
- define a remote interface (which specifies what methods are available
remotely)
- subclass an appropriate RMI server class ("server" implements the
rem.interface)
- run the rmic compiler on the server class (=>generates stub and
skeleton files)
- register the remote object with the RMI registry (contains bindings
name-reference)
ad 1) def. rem. interface
- def. new interface
- make the interface extend the interface java.rmi.Remote
- def. any methods which are going to be available remotely (must by
public)
- each method must declare that it throws the
java.rmi.RemoteException
Note: the interface may contain only 'remote' methods.
Ex(the package stuff not needed):
package myrmi;
public interface MyInterface extends java.rmi.Remote {
public String sayHi(String name) throws
java.rmi.RemoteException;
}
ad 2) subclass server
- implements the remote interface
- specify the remote interface(s) being implemented by the server
- optionally subclass a remote server (e.g.
java.rmi.server.UnicastRemoteObject) (Note: if the server doesn't
subclass some of the server classes, than we need to "export" it - so it
will wait for remote calls on an anonymous port, usually 1099 -
explicitly [in the constructor, I think])
- implement the methods def. in the rem. interface
- def. a constructor for the server, must throw
java.rmi.RemoteException
- create and install the java.rmi.RMISecurityManager
- Note: the implementation must implement the remote interface directly
(not via its parent class). Otherwise rmic won't compile it.
Ex:
package myrmi;
import java.rmi.*;
import java.rmi.server.UnicastRemoteObject;
public class RMIServer extends UnicastRemoteObject implements
MyInterface{
public RMIServer() throws RemoteException {
super();
try {
System.setSecurityManager(new RMISecurityManager());
Naming.rebind("//www.liu.se/~yak/RMIServer",this);/* bind
name and reference in registry, so a client can search there for "RMIServer"
and obtain a reference to it */
} catch (Exception e) {
System.out.println("RMIServer
error"+e.getMessage());
e.printStackTrace();
}
}//constructor
/*implementation of the interface method*/
public String sayHi(String name) throws java.rmi.RemoteException
{
return "Hi "+name;
}
public static void main(String args[]){
try {
new RMIServer();
} catch (RemoteException e) {
System.out.println("RMIServer
error"+e.getMessage());
e.printStackTrace();
}
}
}// server class
ad 3) runing the rmic compiler
After the server class is defined and successfully compiled by a normal
compiler (javac), rmic applies to a .class file.
Ex: $> rmic myrmi.RMIServer // myrmi is the name of the package
into which the file belongs
Produces RMIServer_Skel.class and RMIServer_Stub.class
- used for the communication between the server (Skel file) and a client
(Stub file, works as a proxy)
ad 4) starting the registry
The registry service must be started, so clients can use it.
Ex (Windows): C:\> start rmiregistry 1234 // if start isn't
available, use javaw; 1234 is port number, by default 1099
Ex (UNIX): $> rmiregistry // I just guess it works in this way
...
Then, when the registry runs (def. on port 1099), you can start the server.
Ex: $> java myrmi.RMIServer // don't forget RMIServer implements
the main() method ...
That's all!
Part 2 - client
Ex:
package myrmi;
import java.rmi.*;
public class RMIClient {
public RMIClient() {
try {
// get reference to remote obj.from the rmiregistry:
MyInterface remobj = (MyInterface)
Naming.lookup("//www.liu.se/~yak/RMIServer");
// invoke a remote method
System.out.println( remobj.sayHi("Dick") );
} catch(Exception e) {
System.out.println("RMIClient
error"+e.getMessage());
e.printStackTrace();
}
}// constructor
public static void main(String args[]){
new RMIClient();
}
} // client class
Sockets
Sockets & ObjectInput/OutputStream
- the ObjectInputStream's method readObject is blocking (i.e. blocks
until there is something to be read). I haven't discovered any reliable
way to determine whether there is something or not, in the stream.
- changing an object: if you send an object, change it (e.g. change some
of its fields) and send it again, the receiver receives exactly the same
object as before, namely the change doesn't take effect (from the
receiver's point of view). Conclusion: you can't change the object after
it has been sent, you must create a new one (e.g. create a new object
which is a copy of the old one, change it in the desired way & send
it).
Threads
Note: instead? of threads you can use java.util.Timer or javax.swing.Timer
(source: Java for Practitioners, John Hunt)
- independently running processes
Possible states: runable([R]), sleeping([S]), waiting([W]), interrupted([I])
start()->[R]-sleep()->[S]-time out()->[R]
[R]-wait()->[W]-notify()->[R]
[?]-interrupt()->[I]
[?]-stop()->dead
Creating a thread
Debugging - it's quite a good idea to use the optional string parameter of
the thread constructor, so when you use jdb you'll know what thread is it
talking about (name "serverListenThread" is surely better than "Thread-0")
- sublcass Thread and redefine run()
Ex:
public class Scroller extends Thread {
public void run() {
while(true) { ... perform whatever you want ...}
}
}
...
Thread t = new Scroller("scroller thread");
t.start(); //started
- anonymous Thread subclass
Ex:
Thread th = new Thread("printing anonymous thred") {
public void run() {
System.out.println("Running!");
}
};
th.start();
- define a class implementing Runnable interface. It must define
run()
Ex:
public class Scroller implements Runnable {
public void run() {
while(true) { ... perform whatever you want ...}
}
}
...
Thread t = new Thread(new Scroller()); //note the difference against
the previous case
t.start(); //started
Some methods:
start(), stop(), sleep(long ms)
isAlive() /*started execution and hasn't been stopped yet*/, isInterrupted()
Synchronization
- synchr. methods inside the same class (it means that only 1 of the can
run at a time; if another wants to run. must wait till the running one
finishes). Use 'synchronized' keyword in the method definition:
public synchronized void method(){...} There is one more way (to
synchr. only a part of a method)
- synchr. 2 threads (thread tTwo waits until tOne finishs): (in the body
of tTwo) ... tOne.join() ... code executed after tOne
terminates
Thread interaction
- uses wait(), notify() [only the 1st waiting thread unblocked] and
notifyAll()
- a "common object" use for the interaction; the methods above must be used
in a block synchronized on the common object
Ex (2 threads, one removing things from a queue object, another adding):
// inside the thread that removes:
synchronized (queue) {
queue.wait(); // wait until something is inserted into the queue
newData = queue.next();
}
// inside the thread that adds:
synchronized (queue) {
queue.add(some_object);
queue.notify(); // unblock the first thread waiting for this
queue
}
JavaBeans
(source: Java for Practitioners, John Hunt)
See http://java.sun.com/beans/ for
documentation. Also Java in Nutshell, O'Reilly. Sun's tutorials.
A class is a bean if either it follows the bean naming convention or it
defines the BeanInfo object.
If a bean has a visual appearance, it must subclass the AWT Component (or
some of its subclasses). (True at least when using BeanBox for the
development)
Used together with "bean aware" development tool (very limited demo is the
BeanBox available for free from SUN)
JavaBean is distinguished from a normal class by:
- Providing a public no-argument constructor
- Implementing java.io.Serializable
- Following JavaBeans design patterns (at least one public property must
be defined)
- Set/get methods for properties
- Add/remove methods for events
- Java event model (as introduced by JDK 1.1)
- Being thread safe/security conscious
- Can run in an applet, application, servlet, ...
- And, optionally, having associated BeanInfo class (which is sometimes
necessary, e.g. for some GUI builders)
Properties:
- property itself: private <property type> <prop. name>;
- setter: public void set<Prop. name>(<property type> parameter)
- getter: public <prop. type> get<Prop. name>()
- if the property is boolean, we use in addition: public boolean is<prop.
name>()
Ex: private int max; public void setMax(int par){max=par}; public int
getMax(){return max;}
Events:
Naming conventions for adding/removing listeners:
- add: public void add<listener type> (<listener type> listener)
- remove: public void remove<listener type> (<listener type>
listener)
Bean Notes
- normal methods must not match the conventions mentioned above
- beans communicate via events and (public) methods
BeanInfo
If you use BeanInfo object, it's name must be of form
<BeanName>BeanInfo
Actually, BeanInfo is an interface. The JavaBean API includes some
implementations (e.g. SimpleBeanInfo)
BeanBox tool
- simple tool for developing beans.
Requires the bean files to be placed in a .jar file and either located in
jars directory or loaded from another dir. using BeanBox file menu command
"load jar". The .jar file must contain a manifest file, which contains lines
similar to the following (tells what files are beans):
Ex (manifest.tmp file):
...
Name: package_name/file_name.class
Java-Bean: False
...
JAR archives
Sun: jar - the basics
Jar archive is a single archive containing [compressed] files (not
only .java) and so called manifest file, that describes the content of the
jar archive. A very simple manifest file is created by default. To be able to
use the advanced features of jar archives, you must edit it. (see sun's intro).
For example, if the jar archive is your packed application and you want it to
be runnable, you must add a line similar to the following one into the
manifest file: Main-Class: classname,
where classname is the name of the class containing the main() method.
Creating jar file:
C:\> jar myfile.jar manifest.tmp *.class
- put all .class files in the current directory and the manifest.tmp as the
manifest file into a jar archive called myfile.jar
$> jar cvf jar-file *.java
- puts all .java files (in the current dir.) into jar-file (c-create,
v-verbose, f-output file [must be the last])
Extracting jar file:
$> jar xf jar-file
[archived-file(s)]
- archived-file(s) are the files to be extracted; if omitted, all will be
extracted
$> jar tf jar-file
- lists the content of jar-file
Creating and executing executable jar file:
Old way (java 1.1):
Suppose you have a package called worm that contains the main class
Worm.java (respectively Worm.class)
$> ls
worm/
$> find worm/ -name '*.class' | xargs jar cf
worm.jar
- create a jar archive.
The first part("find ... xargs") finds all the .class files in worm/ and
supplies them as the input parameter for jar.
$> java -cp worm.jar worm.Worm
- run the jar, look for the main method in worm.Worm
New way (java >= 1.2)
Though I have java 2SDK, version > 1.3, I haven't managed to used the new
way (though I followed the instruction). It should work as follows:
$> find worm/ -name '*.class' | xargs jar cmf
main.txt worm.jar
- create jar archive, merge the manifest with the specified file; in this
case, main.txt contains a single line: "Main-Class: worm.Worm"
$> java -jar worm.jar
-run the package. For me it always throws "Failed to load Main-Class manifest
attribute from worm.jar". I wonder why.
GUI and Graphics in Java
- AWT, Swing, Java2D .
AWT
Notes:
- if you want your component to have a particular size, you need to
redefine getPreferedSize: Ex: public Dimension getPreferredSize()
{return new Dimension(400,300);}
- values returned by getWidth() and getHeight() are derived from the
values set by setSize(). So if you just redef. getPreferredSize, the
component will have the size you want, but these two functions will
return zero.
Basic classes: Frame(window frame), Component(=widget; displayed in a frame),
Container (subclass of component, contains other components; e.g. Panel
subclass)
jawa.awt package:
Component (abstract)
|
|-- Canvas
|-- Container (abstract)
|
|-- Window (windows with no borders/menus)
| |
| |-- Frame (has borders, title, frame buttons: close,
min.,max.)
| |-- Dialog
| |
| |-- FileDialog
|
|-- Panel
|
|-- Applet (java.applet package)
Enable closing your window (probably a subclass of Frame):
- let your window implement the WindowListener
- in its constructor, call addWindowListener(this)
- define the listener's methods (must be public) - leave them empty
(methodName(..){}) , except:
public void windowClosing(WindowEvent we){ System.exit(0); }
OR
- in the window's constructor, call addWindowListener(new
MyHandlerName)
- define inside the window the MyHandlerName class, which extends
WindowAdapter
- in MyHandlerName define public void windowClosing(...) as above
To react to an event: 1) implement ActionListener and 2) define public void
actionPerformed(ActionEvent ae)
LayoutManager
GridBagLayout (gbl) is one of the most advanced; requires a
GridBagConstraints (gbc) object to be used
1. set constraints
(gdc.weightx=?,.weighty,.fill,.gridx[column],.gridwidth[how many columns
occupies] etc.)
2. apply the constraints(before adding a component):
gbl.setConstraints(Component toBeAdded, gbc)
3.add component to the container (add(toBeAdded);)
Swing
javax.swing package (for JDK 1.2; for 1.1 it's com.sun.java.swing)
- content can't be added directly to a JFrame; its pane (Container pane =
this.getContentPane();) is used instead of it.
(pane.add(aComponent)).
- use paintComponent() instead of paint()
- if you want to use Swing in an applet, it must be JApplet (the current
browsers have troubles with that, use rather AWT and Applet). Most of the
current browsers do not manage Swing, it's better to use AWT. Otherwise
it becomes quite complicated.
Layouts etc.
BorderLayout
Guarantees to its components their preferred sizes. When it grows, the change
is distributed as follows:
- north, south - only its width will ever grow
- west, east - only its height will ever grow
- center - grows in both directions
GridBagLayout
- Constraints:
- gridx, gridy - the 'coordinates' of the left-top cell occupied by a
component
- gridwidth, gridheight - how many cells in a row/column does the
component occupy (they're 'merged' into one large 'supercell')
- fill - in what direction does the component's cell (or
'supercell') expand (BOTH, NONE - keeps equal size ...)
- anchor - where in the cell is the component placed (this is not
important if fill==BOTH, for in the case it fills the whole cell)
- weightx, weighty - if the container grows, these values determine
what part (ratio) of the growth the (super)cell 'receives' (E.g. if
you have 2 components in a row, with the weightx 0.3 and 0.6, the 2nd
will grow twice more).
- the weights (weightx, weighty) of all columns/rows shall be equal. If
the total weight of a column/row (e.g. 0.6) is smaller than those of the
others (e.g. 1.0), the layout manager gives the difference weight to the
last component of the column/row, i.e. expands it so to fill the
remaining space (in this case it would receive the additional weight 1.0
- 0.6 = 0.4)
More about layouts -see links.
Java2D
Animation
I assume that the animation is done in the paintComponent(Graphics g) method
(it's for Swing what paint() is for AWT), which is called from time to time
(probably by a thread, using the repaint() method). I use rotation and
movement (translation) of the coordinate system to make the effect of an
object moving in various directions. That's easy. The problem is to remember
the current position & orientation between calls of the paintComponent(),
so that in the next call we continue where we stopped in the last one.
- in the first call initialize a non-local variable of the type
AffineTransform , called e.g. aAT, to contain the identity
transform (aAT = new AffineTransform; does it). Use this way,
not aGraphics2D.getTransform()!
- all the transforms (rotations, translations) you want to apply to your
object, apply to aAT (e.g. aAT.translate(30,0) or
aAT.rotate(Math.PI, rotationCentre.x, rotationCentre.y) )
- before you draw the object, apply the transformation done so far to the
graphics object, via its .transform(...) method. Don't use
setTransform(...)! The trouble with .getTransform() and
.setTransform(...) is that they sometimes give strange results,
especially if you use them to get, remeber and restore a transform
between calls. They should be used only inside one call, to get and reset
the unchanged transform (e.g. at the very beginning you use getTransform,
then you apply a transform for one of your objects via .transform(...),
then you reset the initial transform via setTransform and apply a
transform - via .transform(...) - for another object).
Ex: aGraphics2D.transform(aAT);
- And, finally, you can draw your object:
aGraphics2D.draw(myObject);
- Because you applied all the transforms to a non-local variable aAT,
they will be preserved between calls of the paintComponent(...) and if
you want to get where you finished the lust time, just use
aGraphics2D.transform(aAT);
Note: if you apply a new transform (e.g. .rotate(Math.PI)) to the aAT, it's
concatenated on the 'top' of the previous ones. You can think about it as if
the aAT first performed all the old transforms and then, in the end, the last
one you have added. The order here is important. It's different if you first
translate and then rotate or if you first rotate and then translate.
Backwards mapping
If you have an AffineTransform object, aAT and you know a point in a
coordinate system with respect to aAT (i.e. the point in the coordinate
system created by applying aAT) and you want to know what are the point's
coordinates in the space not transformed by aAT (i.e. in the original space),
you can use aAT.transform(Point2D pointInaAT, Point2D
pointInOriginalCoordinates);
Example:
AffineTransform aAT = new AffineTransform();
aAT.translate(50, 80); // move to the coordinates [50,80] in the
original-static- space
Point2D pointInaAT = new Point2D.Double(0,0); // origin of the
coordinates transformed by aAT
Point2D pointInOriginalCoordinates;
aAT.trasnform(pointInaAT, pointInOriginalCoordinates)
System.out.println("Position of pointInaAT in the static coord. system
is: "+ pointInOriginalCoordinates); // prints out values [50, 80]
.
Strings
- '==' can't be used to compare two strings, you must use the
.equals method
- StringTokenizer class can be used to split a string into parts (much
simpler than the StreamTokenizer)
RegExps: Pattern & Matcher
String text = "11 22 3.33 a string to be matched"
// 1. Create a pattern
// Here: something line " int int float any_text...". \\s = whitespace, \\d = decimal.
java.util.regex.Pattern pattern = java.util.regex.Pattern.compile("(\\s*\\d+){2}(\\s*\\d+\\.\\d+).*");
// 2. Get a matcher for it
java.util.regex.Matcher matcher = pattern.matcher( text );
// 3. Find a match. The matcher remebers its position (last match) in the string.
// Find the next match and print it. group can only be called after a successful find.
if( matcher.find() ){ System.out.println( matcher.group() ); }
// 4. Reset the matcher to start searching the string from the beginning.
matcher.reset() // Reset its inernal state => find() would find the first match
Write/read a string into/from a file:
import java.io.*;
PrintWriter writer;
File file = new File("myfilename");
try { file.createNewFile(); } catch (IOException e) {/*do something*/}
try { writer = new PrintWriter( (new FileOutputStream(file)),
true);/*autoflush on*/ } catch (FileNotFoundException e) {/*do
something*/}
writer.print("something"); /*or println */
/* ... */ writer.close();
---
try {
BufferedReader reader = new BufferedReader ( new FileReader("myfilename")
);
String s = reader.readline();
} catch (IOException e) {/*do something*/}
reader.close();
JavaDoc Comments
- see Sun guide
to javadoc comments and javadoc reference.(short
overview of what is discussed in the guide).
- run javadoc (include a list of all packages adn subpackages in the
project):
$> javadoc -d mydir/ -private -windowtitle
'WormDoc' worm worm.bug worm.net worm.chat
- used when generating HTML documentation via javadoc
- of the form /** comment */
- keywords: @author, @version,, @see (what shall the reader read else, form
package.Class#method(type,...)),
(function:) @param(required, form @param name type description),
@return(required unless void or constructor), @exception
- HTML tags may be embedded
- break each line that has over 80 characters
- javadoc omitts some tags by default (author, version). May be changed by
options when running the javadoc( e.g.- author, -version)
- use -d flag to specify the destination folder: $> javadoc -d
mydirectory/HTML MyClass.java
Style etc.
- the first sentence (closed be period followed by space/tab/line break)
shall be on overview of the class/method
- use <code></code> tag for keywords, package names etc.
Ex:
/**
* This counts the number of drivers killed per month.
*
* @author Jakub Holy
* @see CountAccidents
* @param highway_part part of the highway we are interested in
* @exception TooManyDeadException rised when the number of dead exceeds
MAX_DEAD
*/
...
jdb debugger
Since I'm used to gcc, I think that jdb is a bit crappy, but sometimes you
have no other choice than to use it.
- suggestions: when you create a thread in your code, give it a name. The
debugging will be much easier[ new Thread(String name)].
- compile with the -g flag: > javac -g MyClass.java
- start debugger: > jdb MyClass (TCP/IP networking service
must be running)
- some commands: help (or ?), exit (or quit), print myvariable,
...
- thread id: don't be confused by the documentation. Thread's id is the
value including 'x' (0x97 in the following example). At least
sometimes.
Ex: (java.lang.Thread)0x97 main
running
Other
- gcj is a Java to native code (e.g. assembly code) compiler by GNU (open source)
- SWT - Standard Window Toolkit - is st. between AWT and Swing (it uses
native components if there are any, otherwise draws them itself =>
looks more natural than Swing and has more widgets than AWT). By Eclipse (open source).
synchronized key word
Used to synchronize threads on an object (so that only one thread can
access the object at time, the others have to wait).
Use:
- synchronized method method() of an object obj: if a thread
calls obj.method(), the other threads who call obj.method() (on the
same object) have to wait until its call returns. (Note: also static
methods may be synchronized)
- synchronized block of statements has the form:
synchronized(object){ statements }. Only one thread may be executing
the block (the statements) for the object at time.
Makefile for Java
You can use the make utility for java as well as for c or c++. See an example makefile (tested both with make and gmake)
or a more advanced example2.
GCJ - GNU Java Compiler
My version of gcj: cygwin gcj 3.2; Today: June 1 2003
Limitations of GCJ
- So far gcj compiled Java into native code cannot use
Threads for they are not available. When the program is
run it throws exception "Java.lang.InternalError: Thread.start called but
threads not available". Source
- It seems to me that gcj can compile into native code only
.class files created by gcj.
Notes
Compile (Java to native code):
1> gcj -c mypackage/MyJavaProg.java
2> gcj --main=mypackage.MyJavaProg -o myprog.exe
mypackage/MyJavaProg.o
Or both in one step:
> gcj --main=mypackage.MyJavaProg -o myprog.exe
mypackage/MyJavaProg.java
- Flags: '-c' = compile to object (.o), '-o name' = give
name to the output, --main tells gcj name of the class that contain
the main() method that shall be run
- Other flags for the 1st line: '-C' = compile to .class, '-ggdb' create
debug info. for gdb, -On where n=nothing or 0..3; perform optimization
of the given level, 0 implies no optimization.
- It seems to be better to compile like this, not .java->.class->.exe
(less troubles).
If you compile with cygwin gcj 3.2 it prints pretty often a warning like
this: "/cygdrive/c/TEMP/cczKbTsy.s:93: Warning: .stabs:
description field 'a0006' too big, try a different debug
format". It's a bug in the compiler itself which prevents it from
creating debug info thus making it produce useless information about
exceptions. GCJ produces by default some debugging info in the stabs format
(hence '.stabs'). It's highly recommended to use another - not buggy - debug
format (-gdwarf-1, -gvms, -gxcoff etc.).
Debug with GDB
You must set GDB to ignore the signals used by Java garbage collector:
(gdb) handle SIGPWR nostop noprint
(gdb) handle SIGXCPU nostop noprint
GCJ Links
Compiling
Java with GCJ, Debugging
Java with GDB
NetBeans Integrated Development Environment
version 4.0
Compile with "-deprecation": Tools->Options->Building->Ant
Settings, click to the right of "Properties" (...), type on a new line
"javac.deprecation=on".
Create a new GUI JavaBean that can be added to the Palette: see NetBeans:
the Definitive Guide. It refers to an older version but still it's
usable.
version 3.5.1
Create new project using CVS (a versioning system)
Out of NetBeans:
- Create a directory (you want to hold the project in)
- Add it to a CVS repository (how to); don't forget
to check it out and work with that version (to ensure that Cvs
subdirectory is there).
Inside NetBeans:
- Create a new project (Project->Project Manager, click "New")
- Mount your directory as a CVS repository (File->Mount Filesystem,
select Version Control->CVS; enter required info [connection method is
perhaps "Local"])
Links
SUN:
- Java APIs etc.
- developer.sun
- tutorials
- very useful (language, swing and many others)
- RMI
'short' course by jGuru (also explains the rmi architecture ...) -
includes also a working example (the only one out of 3, that I was
able to run :) and the description how to install RMI software over
more machines
- Java 1.4
Specification (javadoc documentation)
Others:
- Java Glossary -
quite useful, includes also stuff (SW...) related to Java.
- Java Gaming
- IBM - tutorials etc. (also about Linux, XML ...)
- Java related Open source and Freeware
- Ant - does the same as
'make' at UNIX, but is Java and XML based (and very useful, say many
people)
- Eclipse - various (SWT ...).
Org. founded by Borland, RedHat, IBM ...
- Tutorials etc. out of sun/IBM
- Bladwin's
serie of (advanced Java) tutorials
- code samples by
Cliff Berg (indeed good!) [printing, remote object browser and many
more]
- layouts -
links to various layouts (not only the standard ones)
- Sites, journals etc.
- developer.com (former
gamelan.com) - lot of articles related to web and especially Java
- Libraries etc.
- Various
- Jars.com - the number one
Java™ review service. (Top
1%).
- IBM SDK for
Linux (1.4.1 .tgz has 54.2MB, JRE .tgz 35.1MB).
- IzPack - an installers
generator for the Java platform producing lightweight installers;
GPL.