Kontakt:
Thorsten Gunkel
63456 Hanau
Deutschland
Mail
Stimm ab und hilf mit diese Seite zu verbessern!Hat die Seite Deine Erwartung erfüllt?
Schreibe Deinen Kommentar doch einfach in das
Gästebuch.
Letzte Änderung: 26-01-2010 00.09
java -Xmx512m
java -version:1.4
Achtung, das Trennzeichen unter Windows ist nicht ":" sondern ";".
So erzeugt man aus einer .java Datei eine .class Datei
javac -classpath "foo/bar.jar:foo/tests.jar:../foo.jar" MyClass.java
Dabei muss man alle jar Dateien angeben, die direkt von der Klasse genutzt werden (also nicht die, die nur von Klassen genutzt werden, die wir aufrufen).
So erzeugt man jar Dateien
jar cf MyJar.jar MyClass.java
Siehe auch die
JAR Dateien erzeugen Anleitung.
So führt man das Java Programm dann aus (jetzt muss man wirklich all jars auflisten die zur Ausführung gebraucht werden)
# java -classpath "foo/bar.jar:foo/tests.jar:../foo.jar:../misc.jar" MyClass
So kann man auf einem entfernten Rechner Java so starten, dass es im lokalen Debugger untersucht werden kann
java -Xdebug -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=n ...
Dabei sorgt
suspend=y
dafür, dass das Programm erst losläuft, wenn der Debugger verbunden ist.
Um den Debugger einzurichten, in Eclipse
open debug digalog
remote java application
new
Rechnername und Port des Java Programms
Ein Interface, darf nur abstrakte Methoden und Konstanten enthalten
/**
* My Interface
*/
package mypackage;
/**
* @author John Doe
*
*/
public interface MyInterface
{
/**
* @param number The number which is added
* @return The new sum
*/
public double add(final int number);
/**
* The limit for the result after the mathematical operations
*/
final static double maxValue=10000;
}
Eine abtrakte Klasse, enthält mindestens eine abstrakte Methode
/**
* An abstract class which will be used for things which are
* not allowed in an Interface
*/package mypackage;
/**
* @author John Doe
*
*/
public abstract class MyAbstractClass
{
/**
* Constructor
*/
public MyAbstractClass()
{
this.value=0;
}
/**
* This is the current value which will be modified by the
* mathematical operations which are offered
*/
protected double value;
}
Eine normale Klasse, darf höchsten von einer anderen Klasse erben, aber von beliebig vielen Interfaces implementieren.
/**
* This class shows that you can implement multiple Interfaces
*/
package mypackage;
/**
* @author John Doe
*
*/
public class MyClass extends MyAbstractClass
implements MyInterface, MyOtherInterface
{
/* (non-Javadoc)
* @see mypackage.MyInterface#add(int)
*/
public double add(final int number)
{
System.out.println("The maxvalue is " + AdderInterface.maxValue);
double res=this.value+=number;
this.value=res;
return res;
}
}
| Type | Größe | Von bis |
| boolean | 1 | |
| char | 2 | |
| byte | 1 | -128...127 |
| short | 2 | -32768...32767 |
| int | 4 | -2147483648 ... 2147483647 |
| long | 8 | -9223372036854775808...9223372036854775807 |
| float | 4 | 1,40239846 * 10^-45 ... 3,40282347 * 10^38 |
| double | 8 | 4,94065645841246544 * 10^-324 ... 1,79769131486231570 * 10^308 |
int i = 4711;
Integer j = i; // j = Integer.valueOf(i)
int k = j; // k = j.intValue()
String str = "HELLO WORLD";
b = ( str instanceof String ); // (1)
b = ( str instanceof Object ); // (2)
b = ( str instanceof Foo ); // (3)
(1) und (2) sind beide wahr, (3) nicht
int x,y;
Foo a, b;
x==y // (1)
a==b // (2)
a.equals(b); (3)
(1) Bei Basistypen ein normaler Test auf Gleichheit
(2) Ansonsten Test ob beides eine Referenz auf das gleiche Objekt ist
(3) Inhaltliche Gleichheit mit equals() testen
Wenn man equals nicht selbst implementiert sieht es so aus:
und equals selbst implementieren, default ist das:
public boolean equals( Object obj )
{
return ( this == obj );
}
Eine mögliche Implementierung:
public boolean equals( Object obj )
{
if ( obj instanceof Foo ) {
Foo tmp = (Foo) obj;
return (bar == tmp.bar)
}
return super.equals( obj );
}
Als Parameter aber Object erwarten und nicht die Klasse für die die Methode gedacht ist. Also nicht:
//public boolean equals(Foo fooObj) {...};
Achtung, wenn man equals ändert, darauf achten, dass aus a.equals(b) auch a.hashcode()==b.hashcode() folgen muss (umgekehrt aber nicht).
Eclipse kann für equals() und hashcode() sinnvolle Vorschläge machen.
Achtung, die Reihenfolge beim equals() Vergleich ist z.B. dann relevant, wenn einer der beiden Objekte null werden kann.
Ist z.B. a potentiell null, b hingegen nicht, kann man das equals von a natürlich nicht aufrufen
// a.equals(b);
b.equals(a);
Können beide null sein, diesen Fall vorher extra abfangen (sonst gibt es eine Exception wenn versucht wird equals auf null aufzurufen).
Kurzschreibweise für bedingte Zuweisung
//if(ungerade) max=l; else max=l-1;
int max=(ungerade) ? l : l-1;
boolean b1 = true || foo(); // (1)
boolean b2 = true | foo(); // (2)
boolean b3 = false & foo(); // (3)
(1) foo() wird nicht aufgerufen
(2) foo() wird aufgerufen
(3) foo() wird aufgerufen
int i[]; // == int [] i;
Foo[] x;
int i[][]; // == int [][] i == int[] i[]
int[] i, x[], y; // == int [] i; int [][]x; int[] y;
int[] prim = { 5, 7, 7 + 4, };
Array mit vorgegebener Größe:
// int hundredElements[ 100 ]; <-- ERROR
int[] hundredElements;
hunderdElements = new int[ 100 ];
int[] prim;
prim = new int[]{ 5, 7, 11, };
System.out.println( hunderedElements.length );
Rechteckiges Array
int i[][]=new int[3][4];
Beliebiges mehrdimensionales Array
int i[][]=new int[3][];
i[0]=new int[7];
i[1]=new int[19];
i[2]=new int[2];
i[3]=new int[100];
foo( new double[]{ 1.1, 2,5, 3.2 } );
double sum = 0;
double[] myarray;
List<Double> mylist=new LinkedList<Double>();
// (1)
for ( int i = 0; i < myarray.length; i++ )
{
sum += myarray[i];
}
// (1b)
for ( double n : mylist )
{
sum += n;
}
// (2)
for (ListIterator<Double> i = mylist.listIterator(); i.hasNext(); )
{
sum+=i.next();
}
// (2b)
for ( double n : myarray )
{
sum += n;
}
(1) Normaler Array Durchlauf
(1b) Kurzschreibweise für (1)
(2) Durchlauf eines Containers mit einem Iterator
(2b) Kurzschreibweise für (2). Man verliert aber den Vorteil gegebenfalls einen Iterator zur Hand zu haben (z.B. zum Löschen von Elementen).
Unnötige Methodenaufrufe in for Schleifen sparen
Häufig sehen for Schleifen so aus
for(int a=0; a<getMaxA(); a++)
Wenn sich der Rückgabewerte der Methode aber für die Dauer des Schleifendurchlaufes nicht ändert und die Methode eine nennenswerte Laufzeit hat, kann man die Schleife über eine weitere Variable deutlich beschleunigen
for(int a, int b=getMaxFoo();
a<b;
a++);
static void arraycopy( Object src, int srcPos, Object dest, int destPos, int length );
int[] y = Arrays.copyOfRange( x, 6, 9 );
So kann man einen String Array in einen String Vector wandeln
String [] myArray;
...
Vector<String> myVector = new Vector<String>(Arrays.asList(myArray));
Arrays.equals( a1, a2 ) ); // (1)
Arrays.deepEquals( a1, a2 ); // (2)
// (1) Referenzen der Elemente im Array müssen gleich sein
// (2) Inhalt muss gleich sein // (2)
Methoden können eine undefinierte Anzahl an Parametern erwarten, ansprechbar wie ein Array
int max( int... x)
{
System.out.println(x.lenght);
}
Foo x,y;
x=new Foo();
y=x.clone();
Flache Kopie von Objekten erzeugen:
void foo(int x)
{
x = 12; // (1)
this.x = 12; // (2)
this.x=x;
}
(1) Zuweisung an lokale Variable x
(2) Zuweisung an Objektvariable x
public enum Weekday
{
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
Der Zugriff erfolgt so:
Weekday.MONDAY
In den case Statements einer switch Anweisung dagegen so:
MONDAY
Über Enums kann man iterieren
for (Tag tag:Weekday.values()) { }
Optional erklären dass man eine Methode des Vaters überschreibt (Fehler falls nicht)
@Override
public void foo( int alter )
Anderen Konstruktor der eigenen Klasse aufrufen
this(5);
muss die erste Anweisung des Konstruktors sein, keine Objektvariablen übergebbar
Wenn man eine Klasse hat, von der es nur wenige Ausprägungen gibt, wie z.B. Boolean.
Dann macht es oft keinen Sinn, dass man mit new beliebig viele verschiedene Objekte dieser Klasse erzeugen kann. Eine besser Variante ist es dann, statt einem Konstruktor eine valueOf() Methode anzubieten
public static valueOf(boolean b)
Diese liefert dann immer wieder die wenigen Objekte zurück die es geben kann, hier z.B. entweder Boolean.TRUE oder Boolean.FALSE. Es darf dann natürlich keine Methode geben, ob den Wert eines solchen Objektes zu verändern, weil sonst auch alle anderen Nutzer dieses Objektes davon betroffen wären.
Initialisieren von Variablen in allen Konstruktoren
class Foo
{
int j=1; // (1)
Foo()
{
this.k=0;
}
Foo( int i )
{
this.k = j;
}
}
entspricht
class Foo
{
int j; // (1)
Foo()
{
this.j=1; // (1)
this.k=0;
}
Foo( int i )
{
this.j = 1; // (1)
this.k = i;
}
}
Bei statischen Variablen
public class Foo
{
static int x = 2;
}
entspricht
public class InitStaticVariable
{
static int x;
static
{
x = 2;
}
}
Konstruktor des Vaters aufrufen
super(5);
Methode des Vaters aufrufen
@Override
public void foo( int alter ) {
super.foo();
...
}
Variable nicht änderbar (wohl aber Methoden aufrufbar die sie ändern)
final int x=3;
final Foo y=new Foo();
y.reset();
Erben nicht möglich
final class Bar
{
// ...
}
Überschreiben nicht möglich
class Foo
{
final void bar();
}
class Foo
{
class Bar
{
}
}
Zum Erzeugen eines Objekts der inneren Klasse, braucht man ein Objekt der äußeren Klasse. Versucht man z.B. in einer statischen Methode der äußeren Klasse ein Objekt der inneren Klasse zu erzeugen würde das fehlschlagen
No enclosing instance of type foo is accessible. Must qualify the allocation with an enclosing instance of type foo (e.g. x.new Bar() where x is an instance of foo).
Nur innere Klassen dürfen Private oder Protected sein. Wenn sie es sind, hat es Einfluss darauf, wer sie benutzen darf.
public class Foo
{
static String s = "HELLO WORLD";
int i = 1;
static class Bar
{
void test()
{
System.out.println(s);
// System.out.println( i ); // (1)
}
}
}
Mitglieds- oder Elementklassen
public class Foo
{
String s = "Hello World";
class Bar
{
void test1()
{
System.out.println( s );
}
//static void test2() { } // (2)
}
}
Von aussen erzeugen
Foo a = new Foo();
Bar b = a.new Bar();
public class Foo
{
public static void main( String[] args )
{
int i = 1;
final int j = 2;
class Bar
{
Bar() {
System.out.println( j );
//System.out.println( i ); // (3) Fehler, da i nicht final
}
}
new Bar();
}
}
Anonyme innere Klassen erben entweder von einer anderen Klasse oder implementieren eine Schnittstelle
class Foo()
{
// ...
}
interface Bar()
{
// ...
}
class Blub{}
{
new Foo()
{
...
}
new Bar()
{
...
}
}
class Foo<T>
{
private T val;
void setValue( T val )
{
this.val = val;
}
T getValue()
{
return val;
}
}
Foo<String> stringFoo = new Foo<String>();
Foo<Integer> intFoo = new Foo<Integer>();
Foo<Point> pointFoo = new Foo<Point>();
class Bar
{
public static <T> T myMethod( T a, T b )
{
//...
}
}
Wenn man Comparable implementiert ist es oft sehr störend, dass man dann als Parameter jede beliebige andere Klasse akzeptieren muss. So kann man es nur für eine Bestimmte Klasse implementieren
public class Foo implements Comparable<Foo>
{
public int compareTo(Foo pOther)
{
}
}
/**
* @see Bar
* @link Bar
* @version 1.01
* @author John Doe
* @param x A number
* @param y Another number
* @return This method always returns 5
* @exception NumberFormatException
* @throws NumberFormatException
* @category Setter
* @deprecated Since yesterday
*/
public int foo(int x, float y)
{
return 5;
}
try
{
// ...
return 5;
}
catch ( Exception e )
{
System.err.println( "Error");
}
finally
{
... // (1)
// return 7; (2)
}
(1) auf jeden Fall, auch nach dem return
(2) keine Exception kann nach oben durchgereicht werden
public class ClubException extends RuntimeException
{
public ClubException()
{
}
public ClubException( String s )
{
super( s );
}
}
kill -3 PID
jstack PID;
Thread.dumpStack();
Sicherstellen dass die gegebene Bedingung erfüllt ist
assert(i>0);
Überwachung der Assertions aktivieren
java -enableassertions foo
java -enableassertions:bar foo
Von der Klasse
Thread
erben und die Methode run überschreiben.
public class Foo extends Thread
{
@Override
public void run()
{
// ...
}
}
Jetzt einfach ein Objekt dieser Klasse erzeugen und die Methode
start()
und nicht
run()
aufrufen.
final int nrOfThreads=4;
Foo [] f=new Foo[nrOfThreads];
for(int i=0; i<nrOfThreads; i++)
{
f[i]=new Foo();
f[i].start();
}
Das Interface
Runnable
implementieren
public class Bar implements Runnable
{
public void run()
{
// ...
}
}
final int nrOfThreads=4;
Thread [] f=new Thread[nrOfThreads];
for(int i=0; i<nrOfThreads; i++)
{
f[i]=new Thread(new Bar());
f[i].start();
}
try
{
for(int i=0; i<nrOfThreads; i++) f[i].join();
}
catch (InterruptedException e) {};
Normalerweise läuft ein Programm so lange weiter, bis auch der letzte Thread sich beendet hat. Ruft man auf einem Thread die Methode
setDaemon(true);
auf, wird auf das Ende dieses Threads nicht mehr gewartet.
Um einen Thread von außen beenden zu können, ist es hilfreich, wenn dieser auf
!isInterrupted()
testet und
InterruptedException
Exceptions fängt und dann selbst
interrrupt()
aufruft. Z.B.
while (!isInterrupted())
{
try
{
...
}
catch ( InterruptedException e )
{
interrupt();
}
}
Jetzt kann man den Thread von außen mit
interrupt()
beenden.
Methode darf nur von einem Thread gleichzeitig betreten werden
public class Foo
{
synchronized public static void bar()
{
// ...
}
}
Pro Objekt darf Methode nur von einem Thread gleichzeitig betreten werden
public class Foo
{
synchronized public void bar()
{
// ...
}
}
Entspricht
public class Foo
{
public void bar()
{
synchronized(this)
{
// ...
}
}
}
Alternative:
lock.lock();
// ...
lock.unlock();
Variablen auf die nur der entsprechenden Thread Zugriff hat (auf private Attribute hätte alle Objekte der entsprechenden Klasse Zugriff).
ThreadLocal foo = new ThreadLocal()
{
protected int bar()
{
return 5;
}
};
Entweder für beliebige Objekte
Collection c = new LinkedList();
c.add("Hello");
c.add("World");
for ( Object x : c ) System.out.println( x );
Oder für spezielle
Collection<String> c = new LinkedList<String>();
for ( String x : c ) System.out.println( x );
ArrayList, LinkedList
HashSet, TreeSet, LinkedHashSet
HashMap, TreeMap, LinkedHashMap, WeakHashMap
- man hat ein Object O
- und einen Key K
- Von dem Key K gibt es ein H(K)
Die HashMap fügt im Hash dann unter H(K) alle Objekte O ein. Es kann mehrere Objekte O geben, die den gleichen Wert für H(K) haben, aber unterschiedliche Werte für K. Ist auch K gleich, wird der vorherige Eintrag überschrieben.
Für die Klasse Integer gilt z.B. H(K)=K, das muss aber nicht so sein.
LinkedList, ArrayBlockingQueue, PriorityQueue
So kann man eine Collection sortieren lassen:
List<Foo> myList;
Collections.sort(myList);
Comparator myComparator=new MyFooComparator();
Collections.sort(myList, myComparator);
Im ersten Fall muss Foo Comparable implementieren, im zweiten Fall kann man seine(n) eigenen Comparator(en) schreiben.
Die Sortierung arbeitet direkt auf dem Container selbst, gegenfalls vorher klonen.
Bei Sortieren kann man leicht das Problem bekommen, dass man zwei Elemente a, b hat, die nicht gleich sind (!a.equals(b)). Allerdings könnten beide Objekte bezüglich einer Sortierung weder kleiner noch größer sein. Beispielsweise bei der Sortierung von Personen nach Schuhgröße. a und b können ganz verschiedene Menschen sein und dennoch genau die selbe Schuhegröße haben. In diesem Fall muss man besonders mit einem TreeSet Container aufpassen. Dieser speichert jedes Objekt höchstens ein mal und aus a.compareTo(b)==0 schließt er (fälschlicherweise?) nur eines der beiden Objekte muss im Container gespeichert werden. Lösung: compareTo() auf mehr Attribute ansetzten oder statt TreeSet eine andere Datenstruktur benutzen (TreeBag?)
Dateien und Verzeichnisse
Class c=null;
try
{
c = Class.forName("foo");
} catch (ClassNotFoundException ex)
{
// ...
}
Nützliche Java Komponenten
Apache Commons.
ToStringBuilder
ToStringBuilder.reflectionToString(this);
new ToStringBuilder(this).append("Name: ", name).append("ID: ", id).toString();
Mit
one-jar kann man mehrere jars in ein großes jar packen und über one-jar selbststartend machen.
Mit dem
JAD Java Decompiler aus class-Dateien wieder lesbaren Quellcode machen. Mit dem Eclipse Plugin
JADClipse sogar vollautomatisch öffnen der entsprechenden Klassen.
Integer.parseInt("042", 10);
Ein BigDecimal erzeugen
BigDecimal x=new BigDecimal("1.123456789");
Ein BigDecimal runden
BigDecimal y=x.setScale(2, BigDecimal.ROUND_HALF_UP);
(x bleibt dabei unverändert)
Mit BigDecimal teilen
BigDecimal a=new BigDecimal("1").setScale(0);
BigDecimal b=new BigDecimal("1.2345");
BigDecimal r=a.divide(b, RoundingMode.HALF_UP);
Achtung, die Genauigkeit beim Teilen zweier BigDecimal wird durch das Objekt festgelegt, dessen divide Methode aufgerufen wird. Das kann zu überraschenden Ergebnissen führen! Daher überlegen, die Genauigkeit beim Teilen anzugeben
BigDecimal r=a.divide(b, 7, RoundingMode.HALF_UP);
Gibt man beim teilen zweier BigDecimal Zahlen keine Roundsart an, und passt das Ergebnis nicht in ein BigDecimal (z.B. 1/3), gibt es eine Exception
java.lang.ArithmeticException: Non-terminating decimal expansion; noexact representable decimal result.
Deshalb beim Teilen immer eine Rundungsart angeben!
jconsole
jvisualvm
Als erstes den Heap Speicher hochsetzen
-Xmx512m
Falls das nicht hilft, aktuellen heap Speicherverbrauch des Programms mit der genannten PID ausgeben
jmap -histo PID
Oder aber abwarten bis es nicht mehr gereicht hat und dann erst auswerten
# java -XX:+HeapDumpOnOutOfMemoryError -jar foo.jar
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid29731.hprof ...
Heap dump file created [1271286324 bytes in 143.266 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
...
Und die Datei dann auswerten
jhat -J-Xmx512m java_pid29731.hprof
...
Started HTTP server on port 7000
25-01-2010 23.33
Links
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
/**
* @see <a href="http://java.sun.com/docs/books/tutorial/uiswing/learn/example2.html">Swing Tutorial</a>
*/
public class MySwingApplication implements ActionListener
{
private static String labelPrefix = "Number of button clicks: ";
private int numClicks = 0;
final JLabel label = new JLabel(labelPrefix + "0 ");
public Component createComponents()
{
JButton button = new JButton("Hit me!");
button.setMnemonic(KeyEvent.VK_I);
button.addActionListener(this);
label.setLabelFor(button);
JPanel pane = new JPanel(new GridLayout(0, 1));
pane.add(button);
pane.add(label);
pane.setBorder(BorderFactory.createEmptyBorder(
30, //top
30, //left
10, //bottom
30) //right
);
return pane;
}
public void actionPerformed(ActionEvent e) {
numClicks++;
label.setText(labelPrefix + numClicks);
}
private static void initLookAndFeel()
{
String lookAndFeel = null;
lookAndFeel = "com.sun.java.swing.plaf.gtk.GTKLookAndFeel";
try
{
UIManager.setLookAndFeel(lookAndFeel);
}
catch (Exception e)
{
System.err.println("Couldn't get specified look and feel");
}
}
private static void createAndShowGUI() {
initLookAndFeel();
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame frame = new JFrame("My Swing Application");
frame.setDefault
CloseOperation(JFrame.EXIT_ON_CLOSE);
MySwingApplication app = new MySwingApplication();
Component contents = app.createComponents();
frame.getContentPane().add(contents, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
Java wird beim Client ausgeführt
Sun Java Applet Tutorial
import javax.swing.JApplet;
import java.awt.Graphics;
public class HelloWorld extends JApplet
{
private static final long serialVersionUID = 1L;
public void init() {};
public void start() {};
public void stop() {};
public void paint(Graphics g)
{
g.drawRect(20, 20, getSize().width - 40, getSize().height - 40);
g.drawString("Hello world!", 40, 40);
}
public void destroy() {};
}
Wird so in HTML eingebettet
<applet width=300 height=300 code="HelloWorld.class"> </applet>
Java wird auf dem Server ausgeführt
JavaServer Pages und Servlets
Verteilte Programmierung mit RMI und WebServices
16-03-2008 09.41
Verbindung aufbauen:
Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
String myURL="jdbc:MyDB:MYTable"
Connection conn=DriverManager.getConnection(myURL);
Connection conn=DriverManager.getConnection(myURL, "MyUserName", "MyPassword");
Andere Variante um Verbindung aufzubauen:
InitialContext ic=new InitialContext();
DataSource ds=ic.lookup("java:comp/env/jdbc/myDB");
DataSource ds=(DataSource) org.apache.derby.jdbc.ClientDataSource();
ds.setPort(1234);
ds.setHost("localhost");
ds.setUser("MyUserName");
ds.setPassoword("MyPassword");
Noch eine Variante um eine Verbindung aufzubauen (getestet mit Oracle). Die passende jar-Datei mit dem Thin-Client für den Zugriff auf Oracle Datenbanken gibt es hier:
JDBC Client Oracle. Diese jar-Datei muss in das Projekt eingebunden werden.
OracleDataSource ods= new OracleDataSource();
ods.setUser("mrfoo");
ods.setPassword("supersecret");
ods.setServerName("myoracleserver.example.com");
ods.setDatabaseName("XE");
ods.setPortNumber(1521);
ods.setDriverType("thin");
OracleConnection conn = (OracleConnection)ods.getConnection();
Fehler:
Exception in thread "main" java.sql.SQLException: Listener refused the connection with the following error:
ORA-12505, TNS:listener does not currently know of SID given in connect descriptor
Der übergebene Datenbankname (hier XE) ist nicht auf dem Server bekannt. Wenn man nicht weiß wie die Datenbank heißt auf dem Server das Kommandozeilentool lsnrctl benutzen und nach Zeilen mit Instance suchen (in folgendem Beispiel heißt die Datenbank tatsächlich XE):
# lsnrctl services
...
Instance "PLSExtProc", status UNKNOWN, has 1 handler(s) for this service...
...
Instance "XE", status READY, has 1 handler(s) for this service...
...
Instance "XE", status READY, has 1 handler(s) for this service...
...
Instance "XE", status READY, has 1 handler(s) for this service...
...
The command completed successfully
Daten auslesen und schreiben
Connection con=DriverManager.getConnection("jdbc:mySubprotocol:mySubName");
Statement stmt=con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
ResultSet srs=stmt.executeQuery("Select price FROM products WHERE price=11.24");
SQLWarning warn=srs.getWarnings();
if (warn!=null) { warn.getMessage(); warn.getSQLState(); warn.getErrorCode(); ... }
while (srs.next())
{
srs.updateFloat("price", srs.getFloat("Price")+2);
srs.updateRow(); // commit
}
ResultSet folgendes:
beforeFirst(); // default am Anfang
afterLast();
next();
previous();
relative(int r);
absoulute(int r); // *
* r=-2 wäre die zweit letzte Zeilen am Ende der Tabelle
Prepared Statements
PreparedStatement ps=con.prepareStatement("UPDATE COFFEES SET SALES = ? WHERE COF_NAME LIKE ?");
Jetzt an zu benennender Stelle den zu nennenden Wert einsetzten:
ps.setInt(1, 75);
ps.setString(2,'FOO');
ps.executeUpdate();
Das geht auch auch direkt mit einer normalen Query:
Statement stmt=con.createStatement(ResultSet.TYPE_SCROLL_SENSETIVE);
Stmt.executeUpdate("Select * FROM ...");
int ExecuteUpdate() liefert die Anzahl der Zeilen zurück die verändert wurden, ResultSet executeQuery() liefert das Ergebnis der Anfrage aus der DB.
Transaktionen
Class.forName("myDriver.ClassName");
Connection con=null;
try
{
con=DriverManager.getConnection("jdbc:mySubprotocol:myDataSource");
con.setAutoCommit(false); // *
for (int i=...)
{
Statement stmt=con.createStatement();
stmt.executeUpdate("INSERT ...");
con.commit(); // *
}
stmt.close();
con.close();
}
catch (SQLException ex)
{
if (con!=null) con.rollback(); // *
}
Alternativ mit Savepoint
Savepoint s1=conn.setSavepoint("tg1");
conn.rollback(s1);
Savepoints löschen:
conn.release(s1);
Oder durch normalen commit Informationen speichern (geht savepoint auch verloren)
conn.commit();
Stored Procedures
Je nach DB etwas anderer Syntax, im pseudocode etwa so:
String myProcedure="create procedure FOO as
select name, age from FRIENDS where age > 50 and age < 75";
Jetzt in DB laden:
Statement stmt=con.createStatement();
stmt.executeUpdate(myProcedure);
Und bei Bedarf aufrufen:
CallableStatement cs=con.prepareCall("{CALL FOO}");
ResultSet rs=cs.executeQuery();
16-03-2008 09.41
Man erzeugt eine neue Klasse, in der mit @Test markierte Methoden einzelne Tests ausführen
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
public class MyCTestClass
{
@Before
public void Myinit()
{
...
}
@Test
public void TestAddMethod()
{
assertTrue(a.add(ZERO).equals(a));
assertTrue(a.add(b).equals(b.add(a)));
}
@Test
public void isDivOK()
{
assertTrue(a.div(ONE).equals(a));
assertTrue(a.mult(b).div(b).equals(a));
}
@Test(expected=NullPointerException.class)
public void nullParameter()
{
a.add(null);
}
}
Die Tests können entweder über die Kommandozeile ausgeführt werden
java org.junit.runner.JUnitCore MyCTestClass
oder aber auch direkt über die IDE, wie hier in Eclipse
26-01-2010 00.09
log4j.properties
# root logger
log4j.rootLogger = ALL, RootAppender
# foo logger
#log4j.logger.foo = INFO, RootAppender
log4j.logger.foo = INFO
# foo.bar logger
#log4j.logger.foo.bar = WARN, RootAppender
log4j.logger.foo.bar = WARN
log4j.appender.RootAppender = org.apache.log4j.ConsoleAppender
log4j.appender.RootAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.RootAppender.layout.ConversionPattern=ROOT %d{ABSOLUTE} [%-30.30C{1}] [%-17t] %-5p %x - %m%n
HelloWorld.java
import org.apache.log4j.Logger;
public class HelloWorld
{
static Logger sFooBarLogger = Logger.getLogger("foo.bar");
static Logger sFooLogger = Logger.getLogger("foo");
static Logger sRootLogger = Logger.getRootLogger();
public static void main (String[] args)
{
sFooBarLogger.debug("FooBar: Debug");
sFooBarLogger.info("FooBar: Info");
sFooBarLogger.warn("FooBar: Warn");
sFooLogger.debug("Foo: Debug");
sFooLogger.info("Foo: Info");
sFooLogger.warn("Foo: Warn");
sRootLogger.debug("Root: Debug");
sRootLogger.info("Root: Info");
sRootLogger.warn("Root: Warn");
}
}
16-03-2008 09.41
Für den Anfang ist
hsqldb sehr gut geeignet. Alle Daten werden dabei in einem Ordner namens "data" im Projektordner als Plaintext abgelegt.
Wir wollen die Klasse hibernate3 in eine Datenbank persistieren bzw die Datenbank auslesen und den Inhalt in dieser Klasse abspeichern. Dazu geben wir der Klasse als erstes einige Attribute und passenden Getter- und Setter-Methoden für all diese Attribute. Zusätzlich noch ein id Attribut vom Type long für Hibernate, das einen privaten Setter hat und nur von Hibernate benutzt werden wird.
Hibernation logt über
log4j, welches über eine
log4j.properties konfiguriert werden sollte.
Hibernation selbst braucht auch eine Configdatei,
hibernate.cfg.xml. In dieser wird definiert wo die Datenbank liegt. Außerdem wird für jede Klasse, die in die Datenbank gemappt werden soll, ein Verweis auf eine Datei aufgeführt, in der das Mapping zwischen der Klasse und einer (oder mehrerer) Tabelle(n) gelistet werden soll.
Ein Verweis auf eine solche Datei sieht z.B. so aus:
<mapping resource="foo/bar/MyClass.hbm.xml"/>
<mapping resource="foo/bar/MyOtherClass.hbm.xml"/>
Ein Mapping für die Klasse "de.tgunkel.de.hibernate3" mit den Attributen "rot", "gruen" und "blau", die auf die Tabelle "MeineFarben" (
Achtung: Keine Leerzeichen in Tabellennamen!) und dort die Spalten "RotAnteil", "GruenAnteil" und "BlauAnteil" gemappt werden sieht z.B. so aus:
<class name="de.tgunkel.de.hibernate3" table="MeineFarben">
<id name="id" column="uid" type="long">
<generator class="increment"/>
</id>
<property name="rot" column="RotAnteil" />
<property name="gruen" column="GruenAnteil" />
<property name="blau" column="BlauAnteil" />
</class>
Bevor man Hibernate wirklich nutzen kann, braucht man erst einmal Zugriff auf eine Hibernate-Session. Am besten schreibt man sich dafür eine kleine
Managerklasse, die einem bei Bedarf eine Session zur Verfügung stellt.
Session session = ManagerHibernateSession.currentSession();
Ganz am Ende müssen wir noch einige hsql spezifische Sachen aufrufen (braucht man für andere Datenbanken so nicht), das lassen wir gleich auch durch die Managerklasse erledigen.
ManagerHibernateSession.hsqlCleanup(session);
Diese kann dann auch noch die Hibernate Session schließen
ManagerHibernateSession.closeSession();
Dazwischen kann man jetzt Hibernate benutzen um Daten in eine Datenbank zu sichern:
Farbe rot=new Farbe(255, 0, 0);
Farbe gruen=new Farbe(0,255,0);
Farbe blau=new Farbe(0,0,255);
// Transaction to write to the db via Hibernation
Transaction myTransaction = session.beginTransaction();
session.save(rot);
session.save(gruen);
session.save(blau);
myTransaction.commit();
Oder auch lesen:
// Transaction to read from the db via Hibernation
myTransaction=session.beginTransaction();
List result = session.createQuery("from Farbe").list();
myTransaction.commit();
for (int i = 0; i<result.size(); i++) {
Farbe neueFarbe = (Farbe) result.get(i);
System.out.println("Farbe: " + neueFarbe.toString());
}
Nicht vergessen mögliche Exceptions zu fangen
catch (HibernateException e)
Dabei ist Farbe kein Tabellenname sondern ein Klassenname der ein Hibernatemapping auf eine Tabelle hat.
Hibernate Objekte können folgende Zustände haben:
| persistent | Verknüpft mit einer eindeutigen Session |
| transient | Noch nie persistent gewesen, nicht mit einer Session verknüpft |
| detached | War mal persistent, ist jetzt aber mit keiner Session mehr verknüpft |
Transistente Objekte werden persistent wenn man save(), persist() oder saveOrUpdate() aufruft.
Persistent werden transient durch delete().
Detached wird ein Objekt durch update() oder saveOrUpdate().
Ein Objekt ist auch dann noch persistent, wenn man Attribute des Objekts verändert hat. Diese Änderungen werden auch automatisch in die Datenbank persistiert.
Siehe auch
xylax.net: Index of Relationships
Wenn man
cascade
benutzt und ein Objekt speichert, das aber andere Objekte verweist, werden auch all die Objekte automatisch gespeichert, auf die verwiesen wird.
Achtung: Löscht man dieses Objekt, werden dann auch alle Objekte gelöscht, auf die verwiesen wurde. Verwendet man kein cascade, muss man die Objekte alle selbst speichern und zwar die zuerst, auf die in anderen verwiesen wird.
Kommt es zu folgendem Fehler
net.sf.hibernate.MappingException: Resource: MyOtherClass.hbm.xml not found
Eine Objekt der Klasse Foo hat ein Objekt vom Typ Bar
<class name="Foo" table="foo"
<one-to-one name="bar" class="Bar" cascade="all" />
</class>
In der Datenbank wird das dann so gelöst, dass man 2 Tabellen hat und der x. Eintrag in der einen Tabelle gehört zum x. Eintrag in der anderen Tabelle (bzw. der Eintrag mit der ID x)
Wie one-to-one, ein Objekt der Klasse Foo verweist auf ein Objekt vom Typ Bar. Jetzt ist es aber möglich dass zwei verschiedene Foo Objekte auf das gleiche Bar Objekt zeigen.
<class name="Foo" table="foo">
...
<many-to-one name="bar" class="Bar" column="bar_id" cascade="all" />
</class>
Gelöst wird das jetzt so dass in jeder Zeile der foo Tabelle eine Spalte ist die angibt welche ID aus der Bar Tabelle dazu passt.
Ein Objekt der Klasse Foo verweist auf eine Liste von Objekten vom Typ Bar. In Java wird das z.B. über ein set gelöst:
private Set myBars;
public Set getBar();
public void setBar(Set bar);
Im Hibernate Mapping sieht das dann so aus:
<class name="Foo" table="foo">
<set name="myBars">
<key column="FooID" />
<one-to-many class="Bar" />
</set></class>
Damit hat man jetzt ein Tabelle mit allen Foo, und eine Tabelle mit allen Bar. In der Bar Tabelle gibt es eine zusätzliche Spalte in der steht zu welchem Foo (welcher Foo-ID) die aktuelle Bar Zeile gehört. Wenn einem Foo mehreren Bar zugeordnen werden sollen, verweisen einfach mehrere Bar Zeilen auf diese Foo-ID.
Damit die Bar automatisch zum passenden Foo verweisen braucht man noch eine add Methode die ein einzelnes Bar hinzufügt.
public void addBar(Bar b)
{
this.myBars.add(b);
}
Problem: Beim Hinzufügen wird erst ein neues Bar mit leerem Verweis erzeugt und dann per Update der Verweis gesetzt. Für kurze Zeit ist der Verweis daher null, was gegen not null constrains verstossen wird. Siehe auch
Hibernate Parent/Child.
Siehe auch
Hibernate inverse mapping.
Angenommen man hat ein Objekt Foo das auf ein Set von Bar verweist. Dann wird es vermutlich eine Methode
Foo.add(Bar b)
geben um einem Foo verschiedene Bar zuzuordnen. Manchmal ist es praktisch auch von den zugeordneten Bar wieder auf das Foo zu kommen dem das Bar zugeordnet ist. Dazu würde man sich dann z.B. eine solche Methode schreiben
Bar.setOurFoo(Foo f)
.
Solange jetzt jedem Foo nur genau dann ein Bar zugeordnet ist, wenn dem Bar auch das Foo zugeordnet ist, hat man noch kein Problem. Jetzt könnte aber jemand auf die verrückte Idee kommen, und einem Foo ein Bar zuzuordnen, das selbst gar nicht dem Foo zuzuordnen ist. Weil diese inverse Beziehung entweder keinen Mehrinformation für Hibernate beinhaltet, oder sogar zu widersprüchlichen Aussagen führt, kann man eine solche Beziehung als
inverse
markieren damit Hibernate sie ignoriert.
Man hat zwei Tabellen
Parent:
Child:
Beliebig viele Child Einträge können einem Parent Eintag zugewiesen werden, indem die idrefP Spalte auf eine idP zeigt.
So sieht ein Parent Objekt dann aus
@Entity
class Parent
{
@Id
Long idV;
@OneToMany(mappedBy="myParent")
@JoinColumn(name="idrefP")
List<Child> myChildrend;
}
Die Klasse enthält eine Liste von allen Child Objekten, die auf die Klasse zeigen. Das ist ein Unterschied zur Tabelle, wo man eine Parent Zeile keine Referenz auf Ihre Child Objekte hat.
Außerdem enthält die Klasse noch den Hinweis in welchem Attribut die Child Objekte die Referenz auf Ihre Parent Klasse halten und wie die Spalte in der Child Datenbanktabelle dafür heißt.
Die Child Klasse sieht so aus
@Entity
class Child
{
@Id
Long idC;
@ManyToOne
@JoinColumn(name="idrefP", insertable=false, updatable = false )
Parent myParent;
}
Hier ist nur der Hinweis hinterlegt, welche Spalte in der Tabelle als Referenz auf das Vater Objekt benutzt wird.
Speichert man ein Parent Objekt werden auch alle Child Objekte gespeichert. Damit die Child Objekte umgekehrt nicht versuchen dann wieder Ihren Vater zu speichern setzt man
insertable=false, updatable = false
erhält man einen Fehler
Vergisst man das erhält man
Repeated column in mapping for entity: (should be mapped with insert="false" update="false")
Wenn Hibernate die ID einer Klasse aus einer SQL Sequence ziehen soll, reserviert er per Default 50 IDs. Wenn man das nicht benötigt, kann man den Wert über allocationSize verändern
@SequenceGenerator(name = "ACCOUNTING_OID", sequenceName = "ACCOUNTING_OID", allocationSize=1)
HQL
Bind parameters
- named parameter
Query q = sess.createQuery("from MyFoo foo where foo.name = :name");
q.setString("name", "Bar");
Iterator foos = q.iterate();
- positional parameter
Query q = sess.createQuery("from MyFoo foo where foo.name = ?");
q.setString(0, "Bar");
Iterator foos = q.iterate();
- named parameter list
List names = new ArrayList();
names.add("Bar1");
names.add("Bar2");
Query q = sess.createQuery("from MyFoo foo where foo.name in (:namesList)");
q.setParameterList("namesList", names);
List foos = q.list();
Angenommen man hat zwei Tabellen t1 und t2 und zwei Klassen C1 und C2 mit Hibernate Mappings.
Dann kann man
from C1
oder
from C2
schreiben. Man kann dann auch immer ein ein cartesisches Produkt bilden
from C1, C2
Wenn es zwischen t1 und t2 eine Beziehung über einen Schlüssel gibt, kann man den auch im Mapping der beiden Klassen abbilden. Nehmen wir weiter an, C1.ref sei eine gemappte Referenz auf C2 Klassen. Dann kann man auch
from C1 inner join C1.ref
schreiben, um C1 und alle über ref verknüpften C2 Objekte zu beziehen (ohne eine explizite Verknüpfungsbedingung angeben zu müssen). Man bekommt dann einen Array zurück, in dem in einer Zeile die jeweils verknüpften Objekten enthalten sind.
Wenn man jetzt alle C1 ausfiltern möchte, die auf ein C2 verweisen, welches ein price Attribute ungleich null hat, muss man nicht mal mehr einen Join formulieren. Man kann direkt auf die Referenz Bedingungen abfragen, und Hibernate führt die notwendigen Joins automatisch aus
from C1 AS a where a.ref.price is not null
So kann man erzwingen, dass alle verknüpften Objekte sofort mitgeladen werden
from Foo fetch all properties where foo.bar=...
Man kann in einer HQL Query auch bestimmen, welche Objekte oder Attribute man zurückgeliefert bekommt
select A,D from A,B,C,D
Wenn man über HQL Objekte löschen will, geht das eigentlich so
int deletedEntities = s.createQuery( "delete Foo f where f.id = :myID" ).setString( "myID", 42 ).executeUpdate();
Das kann mindestens an zwei Dingen scheitern:
Ein Workarround ist dann, die zu löschenden Objekte erst mal mit Hibernet auszulesen und dann mit delete zu entfernen
Query query = mySession.createQuery("select from Foo f where f.id=:myID").setString("myID", 42);
Transaction myTransaction = mySession.beginTransaction();
{
@SuppressWarnings("unchecked")
List<Foo> lSearchResult= (List<Foo>) query.list();
Iterator<Foo> i=lSearchResult.iterator();
while(i.hasNext()) mORSPropertySession.delete(i.next());
}
Oder natürlich einfach SQL statt HQL benutzen.
Hibernate Batch processing
Wenn man in einer Schleife viele Hibernateobjekte schreibt, alle n Schleifendurchläufe
session.flush();
session.clear();
aufrufen und das hier setzten (n durch die tatsächliche Anzahl ersetzten)
hibernate.jdbc.batch_size n
Hibernate Criteria Queries
Criteria crit=session.createCriteria(Product.class);
Criterion my_age=Restrictions.gt("age", new Integer(42));
Criterion my_name=Restrictions.like("name", "Mr. Foo%");
LogicalExpression my_or=Restrictions.or(my_age, my_name);
crit.add(my_or);
List results=crit.list();
Man benötigt die entsprechenden jars. Mindestens
hibernate-annotations.jar
ejb3-persistence.jar
Einige Annotations sind dem Hibernate jar, einige sind auch für
EJB3 übernommen worden und andere sogar in die
Java Persistence API.
Falls eine Annotation aus mehr als einem der drei Quellen zu beziehen ist, dann die allgemeinere Quelle nehmen.
Die benutzte Session Factory muss aus einer AnnotationConfiguration sein.
sessionFactory = new AnnotationConfiguration().buildSessionFactory();
In der cfg.xml verweist man statt auf eine hbm.xml
<mapping resource="foo/Bar.hbm.xml" />
auf eine Klasse
<mapping class="de.foo.Bar" />
Die Klasse muss dann für jede Spalte, die man aus der entsprechenden Tabelle mappen möchte ein gleichnamiges Attribut enthalten (erster Buchstabe sollte kleingeschrieben werden). Die kleinste Version einer solchen Klasse sieht ungefähr so aus
@Entity(name="Bar")
public class Bar
{
private Long id;
@ID
public Long getId()
{
return id;
}
}
Lässt man @Entity noch weg, ist die Klasse in Queries nur über vollständige Klassennamen zu erreichen, also
from de.foo.Bar
statt
from Bar
Schreibt man die @ID Annotation vor eine Klassenvariable, greift Hibernate auf alle Attribute direkt zu, schreibt man sie vor einen Getter, wird für alle Attribute ein Getter und Setter benutzt. Der Getter und Setter muss genau die gleiche Groß- und Kleinschreibung in seinem Namen benutzen, wie das Attribut der Klasse (abgesehen vom ersten Buchstaben, der im Getter groß-, im Attribut kleingeschrieben werden muss).
Von allen anderen Attributen außer dem ID Attribut wird automatisch erwartet dass sie eine gleichlautende Entsprechung in der Datenbanktabelle haben. Mit dem Attribut
@Transient
kann man Attribute und Methoden davon ausschließen.
Auch mit Annotations kann man Benannte Queries hinterlegen (auch wenn das in einer Java Klasse vermutlich weit weniger Sinn macht, als es das in einer hbm.xml gemacht hat).
@Entity(name="Bar")
@NamedQuery(name="foo", query="select a from Bar b where b.id = :myid")
public class Bar
{
...
So kann man aber nur eine Named Query pro Klasse haben, sonst gibt es eine
Duplicate annotation @NamedQuery
Fehlermeldung.
Wenn man mehr als eine Named Query benötigt geht das so;
@Entity(name="Bar")
@NamedQueries({
@NamedQuery(name = "a" query = "select a from A"),
@NamedQuery(name = "b" query = "SELECT b from B")
})
public class Bar
{
...
Mit folgendem Eintrag in der hibernate.cfg.xml
<property name="hibernate.show_sql">true</property>
bekommt man die ausgeführten (Prepared) SQL Statements angezeigt.
Und wenn man das in log4j setzt, sieht man auch die Parameter der Prepared Statements
log4j.logger.net.sf.hibernate.SQL = TRACE
log4j.logger.net.sf.hibernate.type = TRACE
log4j.logger.org.hibernate.SQL = TRACE
log4j.logger.org.hibernate.type = TRACE
In einer Schleife wird ab und zu ein commit ausgeführt
Transaction t=beginTransaction();
Query q=...;
Iterator i=q.iterate();
while (i.hasNext())
{
Object o=i.next();
...
s.update(o);
counter++;
if(counter % MAXOBEJECTSPERCOMMIT)
{
t.commit();
}
}
In Hibernate 2.x war das kein Problem, in Hibernate 3.x ist nach dem commit aber leider die Connection geschlossen.
org.hibernate.exception.GenericJDBCException: could not get next iterator
result - java.sql.SQLException: Closed Resultset: next
Die Ursache liegt im neuen Default
connection release mode der in Hibernate 3.x auf AFTER_TRANSACTION gesetzt wurde. Damit wird nach dem Commit die Connection geschlossen.
Entweder auf den Cnnection Release Mode on_close wechseln (wovon aber abgeraten wird) oder eben erst am Ende das Commit ausführen.
25-01-2010 22.27
Das Apache
ANT Werkzeug. Vergleichbar mit Makefiles, Schwerpunkt liegt aber nicht auf Abhängigkeiten (das kann Java selbst) sondern auf der Bereitstellung plattformunabhängiger Befehle (z.B. zum Kopieren von Dateien).
Links
<project name="MyProject" default="compile" basedir=".">
<!-- set global properties for this build -->
<property name="src" location="src" />
<property name="build" location="build" />
<property name="dist" location="dist" />
<property name="mainclass" value="de.tgunkel.Test.Foo" />
<property name="distjarname" value="MyProject" />
<!-- path for compiling the code -->
<path id="compilepath">
<fileset file="../../src/lib/foo_1.5.0.jar" />
<fileset dir="../../src/lib/">
<include name="**/*.jar"/>
</fileset>
</path>
<!-- path for running the code -->
<path id="runpath">
<path refid="compilepath"/>
<pathelement location="build"/>
<pathelement location="etc"/>
<fileset file="../../lib/otherlib/foo-2.0.0.jar" />
</path>
<!-- clean -->
<target name="clean" description="clean">
<!-- <delete dir="${build}" /> -->
<delete includeemptydirs="true">
<fileset dir="${build}" includes="**/*"/>
</delete>
</target>
<!-- Some initial stuff -->
<target name="init" description="init">
<!-- Create the time stamp -->
<tstamp/>
<mkdir dir="${build}"/>
<mkdir dir="${dist}"/>
</target>
<!-- compile it -->
<target name="compile" description="compile the source" depends="init">
<javac srcdir="${src}" destdir="${build}">
<classpath refid="runpath">
</classpath>
</javac>
</target>
<!-- run the compiled code -->
<target name="run" depends="compile" description="Run the pro
gram" >
<java classname =3D "${mainclass}">
<arg value="foo" />
<arg value="bar" />
<arg value="42" />
<classpath refid="runpath" />
</java>
</target>
<!-- create a jar -->
<target name="jar" description="makes a jar" depends="compile">
<jar basedir="${build}" compress="true" jarfile="${dist}/${distjarname}">
<manifest>
<attribute name="Built-By" value="Thorsten Gunkel" />
<attribute name="Main-Class" value="${mainclass}" />
<!-- You need the whole run time path here for an executable jar
<attribute name="Class-Path" value="../../../src/lib/foo_1.0.0.jar" />
-->
</manifest>
</jar>
</target>
</project>
Wenn man erreichen möchte, dass sich kein Code eingebaut wird, der nur mit Warnungen übersetzt wird, kann man diese nützlich Option setzen:
<compilerarg value="-Xlint:unchecked"/>
Jede Warnung wird dann wie ein Fehler behandelt und führt zum Abbruch des Compilers. So werden Warnungen sehr früh bemerkt.
So kann man mit ANT in Dateien Textersetzung durchführen
<project basedir=".">
<target name="build" description="Replace some strings">
<replace dir=".">
<include name="myfiles/**" />
<replacefilter token="__FOO__" value="BAR" />
<replacefilter token="__43__" value="42" />
</replace>
</target>
</project>
<jvmarg value="-Xdebug" />
<jvmarg value="-Xnoagent" />
<jvmarg value="-Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y" />
17-01-2010 01.49
So kann man an ein jar das Javadoc anhängen: Das Projekte anklicken, Menü, Project, Properties, Libraries, [jar], aufklappen, javadoc location.
Breakpoints können nur den aktuellen Thread anhalten, oder gleich die ganze VM. Den Default kann man so festlegen
Preferences -> Java -> Debug -> [ Suspend Execution | Suspend Thread ]
In der Debug View kann man mit dem J! Symbol Brakepoints setzen, die nur bei Exceptions aktiv werden
Preferences -> Java -> Code -> Style -> Formater
Dort New anklicken und ein eigenes anlegen.
Mit
CTR SHIFT F
anwenden lassen
Das Eclipse Error Log liegt im Workspace Ordner und endet auf .log.
Eclipse 3.1.1 und PermGen zu klein? Wenn in der eclipse.ini sowas steht
-XX:MaxPermSize=256m
dann mal statt dessen das hier probieren
--launcher.XXMaxPermSize 256m
25-01-2010 22.27
JRat
So startet man das zu messende Programm
java -javaagent:shiftone-jrat.jar ...
So kann man sich die Ergebnisse mit dem mitgelieferten Viewer ansehen
java -Xmx256M -jar shiftone-jrat.jar
JRat hatte allerdings Probleme mit Hibernate und Annotations.
JIP
So startet man das zu messende Programm
java -javaagent:[DIR]\profile.jar ...
Am einfachsten ist es, wenn [DIR] ein absoluter Pfad ist.
Andere Variante
java -javaagent:[DIR]\profile.jar -Dprofile.properties=[DIR2]\profile.properties
Auch hier ist es einfacher, wenn [DIR] und [DIR2] absolute Pfade sind.
Im Paket ist ein Beispiel für eine profile.properties enthalten. Damit man sich die Ergebnisse visualisieren lassen kann, muss man in der properties mindestens
output=both
setzen. Wenn man in der properties den Eintrag
file
auf einen Ordner zeigen lässt, dann wird jeder neue Lauf in eine neue Datei geschrieben.
Ebenfalls nützlich ist der Eintrag
output-method-signatures=yes
So kann man sich die Ergebnisse schließlich visualisieren lassen
java -jar jipViewer.jar [DIR3]/profile.xml
Wobei hier [DIR3] der Ordner ist, in den JIP die Messwerte Schreiben sollte.
25-01-2010 22.27