public abstract class ClassLoader extends Object
すべての Class
オブジェクトには、それを定義した ClassLoader への参照
が含まれています。
配列クラスの Class オブジェクトは、クラスローダーによっては作成されず、Java Runtime の要求に応じて自動的に作成されます。配列クラスのクラスローダー (Class.getClassLoader()
から返される) は、その要素の型のクラスローダーと同じになります。要素の型がプリミティブ型の場合、配列クラスはクラスローダーを持ちません。
アプリケーションは、Java 仮想マシンが動的にクラスをロードするように拡張するために、ClassLoader のサブクラスを実装します。
クラスローダーは一般的に、セキュリティーマネージャーがセキュリティードメインを示すために使われます。
ClassLoader クラスは、委譲モデルを使ってクラスとリソースを探します。ClassLoader の各インスタンスは、関連する親クラスローダーを持ちます。クラスまたはリソースを見つけるために呼び出されると、ClassLoader インスタンスはそれ自体でクラスまたはリソースの検索を試みる前に、その検索を親クラスに委譲します。「ブートストラップクラスローダー」と呼ばれる仮想マシンの組み込みクラスローダーはそれ自体では親を持たず、ClassLoader インスタンスの親として動作します。
クラスの並行ロードをサポートするクラスローダーは並行可能なクラスローダーと呼ばれ、そのクラス初期化時に ClassLoader.registerAsParallelCapable
メソッドを呼び出して自身を登録する必要があります。ClassLoader クラスはデフォルトで並行可能として登録されます。ただしそのサブクラスについては、並行可能な場合には自身を登録する必要があります。
委譲モデルが厳密に階層化されていない環境では、クラスローダーは並行可能である必要があります。そうでないと、クラスロード時にデッドロックが発生する可能性があります。これは、クラスロード処理中にローダーのロックが保持されるからです (loadClass
メソッドを参照)。
通常、Java 仮想マシンは、プラットフォームに依存しない方法でローカルファイルシステムからクラスをロードします。たとえば、UNIX システムでは仮想マシンは、CLASSPATH 環境変数によって定義されたディレクトリからクラスをロードします。
ただし、ファイルから作成できないクラスもあります。このようなクラスは、ネットワークなどのほかのソースから作成したり、アプリケーションが構築したりします。メソッド defineClass
は、バイトの配列をクラス Class のインスタンスに変換します。この新しく定義されたクラスのインスタンスを作成するには、Class.newInstance
を使用します。
クラスローダーで作成したオブジェクトのメソッドとコンストラクタは、ほかのクラスを参照できます。参照するクラスを判定するために、Java 仮想マシンは、クラスを最初に作成したクラスローダーの loadClass
メソッドを呼び出します。
たとえば、アプリケーションはネットワーククラスローダーを作成して、サーバーからクラスファイルをダウンロードできます。コードは次のようになります。
ClassLoader loader = new NetworkClassLoader(host, port); Object main = loader.loadClass("Main", true).newInstance(); . . .
ネットワーククラスローダーのサブクラスは、ネットワークからクラスをロードするために findClass
メソッドと loadClassData メソッドを定義する必要があります。クラスを作成するバイトを一度ダウンロードしたら、defineClass
メソッドを使ってクラスインスタンスを生成するべきです。実装の例を次に示します。
class NetworkClassLoader extends ClassLoader { String host; int port; public Class findClass(String name) { byte[] b = loadClassData(name); return defineClass(name, b, 0, b.length); } private byte[] loadClassData(String name) { // load the class data from the connection . . . } }
ClassLoader のメソッドの String
パラメータとして指定するクラス名はすべて、『Java™ 言語仕様』で規定されたバイナリ名である必要があります。
次に、有効なクラス名の例を示します。
"java.lang.String" "javax.swing.JSpinner$DefaultEditor" "java.security.KeyStore$Builder$FileBuilder$1" "java.net.URLClassLoader$3$1"
resolveClass(Class)
修飾子 | コンストラクタと説明 |
---|---|
protected |
ClassLoader()
getSystemClassLoader() メソッドから返された ClassLoader を親クラスローダーとして使用し、新しいクラスローダーを作成します。 |
protected |
ClassLoader(ClassLoader parent)
指定された親クラスローダーを使って、委譲のために新しいクラスローダーを作成します。
|
修飾子と型 | メソッドと説明 |
---|---|
void |
clearAssertionStatus()
このクラスローダーのデフォルトのアサーションステータスを false に設定し、クラスローダーに関連付けられたパッケージデフォルトまたはクラスのアサーションステータス設定をすべて破棄します。
|
protected Class<?> |
defineClass(byte[] b, int off, int len)
非推奨。
defineClass(String, byte[], int, int) に置き換えられています |
protected Class<?> |
defineClass(String name, byte[] b, int off, int len)
バイトの配列を Class クラスのインスタンスに変換します。
|
protected Class<?> |
defineClass(String name, byte[] b, int off, int len, ProtectionDomain protectionDomain)
オプションの ProtectionDomain を使って、バイトの配列を Class クラスのインスタンスに変換します。
|
protected Class<?> |
defineClass(String name, ByteBuffer b, ProtectionDomain protectionDomain)
オプションの ProtectionDomain を使って、
ByteBuffer をクラス Class のインスタンスに変換します。 |
protected Package |
definePackage(String name, String specTitle, String specVersion, String specVendor, String implTitle, String implVersion, String implVendor, URL sealBase)
この ClassLoader で名前を使ってパッケージを定義します。
|
protected Class<?> |
findClass(String name)
指定されたバイナリ名を持つクラスを探します。
|
protected String |
findLibrary(String libname)
ネイティブライブラリの絶対パス名を返します。
|
protected Class<?> |
findLoadedClass(String name)
|
protected URL |
findResource(String name)
指定された名前を持つリソースを検索します。
|
protected Enumeration<URL> |
findResources(String name)
指定された名前を持つすべてのリソースを表す
URL オブジェクトの列挙を返します。 |
protected Class<?> |
findSystemClass(String name)
指定されたバイナリ名を持つクラスを探して、必要に応じてロードします。
|
protected Object |
getClassLoadingLock(String className)
クラスロード操作用のロックオブジェクトを返します。
|
protected Package |
getPackage(String name)
このクラスローダーかその祖先のどれかによって定義された Package を返します。
|
protected Package[] |
getPackages()
このクラスローダーとその祖先によって定義されたすべての Package を返します。
|
ClassLoader |
getParent()
委譲のための親クラスローダーを返します。
|
URL |
getResource(String name)
指定された名前を持つリソースを検索します。
|
InputStream |
getResourceAsStream(String name)
指定されたリソースを読み込む入力ストリームを返します。
|
Enumeration<URL> |
getResources(String name)
指定された名前を持つすべてのリソースを検索します。
|
static ClassLoader |
getSystemClassLoader()
委譲のためのシステムクラスローダーを返します。
|
static URL |
getSystemResource(String name)
クラスをロードするために使用される検索パスから、指定された名前のリソースを探します。
|
static InputStream |
getSystemResourceAsStream(String name)
クラスをロードするのに使用される検索パスから、指定された名前のリソースを、読み込み用にオープンします。
|
static Enumeration<URL> |
getSystemResources(String name)
クラスをロードするために使用される検索パスから、指定された名前のすべてのリソースを探します。
|
Class<?> |
loadClass(String name)
指定されたバイナリ名を持つクラスをロードします。
|
protected Class<?> |
loadClass(String name, boolean resolve)
指定されたバイナリ名を持つクラスをロードします。
|
protected static boolean |
registerAsParallelCapable()
呼び出し元を並行可能として登録します。
|
protected void |
resolveClass(Class<?> c)
指定されたクラスをリンクします。
|
void |
setClassAssertionStatus(String className, boolean enabled)
このクラスローダーの指定されたトップレベルクラスおよびそこに含まれるネストされたクラス内に対して、目的のアサーションステータスを設定します。
|
void |
setDefaultAssertionStatus(boolean enabled)
このクラスローダーのデフォルトのアサーションステータスを設定します。
|
void |
setPackageAssertionStatus(String packageName, boolean enabled)
指定されたパッケージデフォルトのアサーションステータスを設定します。
|
protected void |
setSigners(Class<?> c, Object[] signers)
クラスの署名者を設定します。
|
protected ClassLoader(ClassLoader parent)
セキュリティーマネージャーがある場合はその checkCreateClassLoader
メソッドが呼び出されます。これはセキュリティー例外となる場合があります。
parent
- 親クラスローダーSecurityException
- セキュリティーマネージャーが存在し、その checkCreateClassLoader メソッドが新しいクラスローダーの作成を許可しない場合protected ClassLoader()
getSystemClassLoader()
メソッドから返された ClassLoader を親クラスローダーとして使用し、新しいクラスローダーを作成します。
セキュリティーマネージャーがある場合はその checkCreateClassLoader
メソッドが呼び出されます。これはセキュリティー例外となる場合があります。
SecurityException
- セキュリティーマネージャーが存在し、その checkCreateClassLoader メソッドが新しいクラスローダーの作成を許可しない場合public Class<?> loadClass(String name) throws ClassNotFoundException
loadClass(String, boolean)
メソッドの場合と同じです。Java 仮想マシンがこのメソッドを呼び出して、クラス参照を解決します。このメソッドを呼び出すことは、loadClass(name, false)
を呼び出すことに相当します。 name
- クラスのバイナリ名ClassNotFoundException
- クラスが見つからなかった場合protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
クラスがすでにロードされていないかチェックするために findLoadedClass(String)
を呼び出す。
親クラスローダーで loadClass
メソッドを呼び出す。親が null の場合、仮想マシンに組み込まれたクラスローダーが代わりに使用される。
findClass(String)
メソッドを呼び出してクラスを探す。
上記の手順でクラスが見つかった場合、resolve フラグが true のときには、このメソッドは見つかった Class オブジェクトに対して resolveClass(Class)
メソッドを呼び出します。
ClassLoader のサブクラスでは、このメソッドではなく findClass(String)
をオーバーライドすることをお勧めします。
このメソッドは、オーバーライドされないかぎり、クラスのロード処理中に、getClassLoadingLock
メソッドの結果に対して同期を行います。
name
- クラスのバイナリ名resolve
- true の場合は、クラスを解決するClassNotFoundException
- クラスが見つからなかった場合protected Object getClassLoadingLock(String className)
className
- ロードするクラスの名前NullPointerException
- 並行可能として登録されていて、className が null の場合loadClass(String, boolean)
protected Class<?> findClass(String name) throws ClassNotFoundException
loadClass
メソッドによって呼び出されます。デフォルトの実装は ClassNotFoundException をスローします。 name
- クラスのバイナリ名ClassNotFoundException
- クラスが見つからなかった場合@Deprecated protected final Class<?> defineClass(byte[] b, int off, int len) throws ClassFormatError
defineClass(String, byte[], int, int)
に置き換えられています。b
- クラスデータを構成するバイト。off から off+len-1 までの位置にある byte は、『Java™ 仮想マシン仕様』で定義される有効なクラスファイルの形式を持つoff
- クラスデータの b 内での開始オフセットlen
- クラスデータの長さClassFormatError
- データが有効なクラスを含まなかった場合IndexOutOfBoundsException
- off または len が負の場合、または off+len が b.length より大きい場合SecurityException
- このクラスとは異なる一連の証明書で署名されたクラスを含むパッケージにこのクラスを追加しようとした場合、または「java.
」で始まる完全指定名を持つパッケージ内でクラスを定義しようとした場合。loadClass(String, boolean)
, resolveClass(Class)
protected final Class<?> defineClass(String name, byte[] b, int off, int len) throws ClassFormatError
このメソッドは、新しく定義されたクラスにデフォルトの ProtectionDomain
を割り当てます。ProtectionDomain には事実上、Policy.getPolicy().getPermissions(new CodeSource(null, null))
の呼び出し時に返されるのと同じアクセス権のセットが付与されます。デフォルトドメインは、defineClass
の初回呼び出し時に作成され、以降の呼び出し時には再利用されます。
特定の ProtectionDomain をクラスに割り当てるには、ProtectionDomain をその引数の 1 つとしてとる defineClass
メソッドを使用します。
name
- クラスの予想されるバイナリ名。不明な場合は nullb
- クラスデータを構成するバイト。off から off+len-1 までの位置にある byte は、『Java™ 仮想マシン仕様』で定義される有効なクラスファイルの形式を持つoff
- クラスデータの b 内での開始オフセットlen
- クラスデータの長さClassFormatError
- データが有効なクラスを含まなかった場合IndexOutOfBoundsException
- off または len が負の場合、または off+len が b.length より大きい場合SecurityException
- このクラス (未署名) とは異なる証明書セットを使って署名されたクラスを含むパッケージに、このクラスを追加しようとした場合、または name が「java.」で始まる場合。loadClass(String, boolean)
, resolveClass(Class)
, CodeSource
, SecureClassLoader
protected final Class<?> defineClass(String name, byte[] b, int off, int len, ProtectionDomain protectionDomain) throws ClassFormatError
defineClass(String, byte[], int, int)
のドキュメントで指定されているように、デフォルトドメインがクラスに割り当てられます。最初にクラスを解決してからでなければ、クラスを使用することはできません。
パッケージで定義される最初のクラスにより、そのパッケージ内で続いて定義されたすべてのクラスに必要な、証明書の正確なセットが決まります。クラスの証明書のセットは、そのクラスの ProtectionDomain 内の CodeSource
から取得します。そのパッケージに追加されたクラスには同一の証明書のセットが含まれている必要があり、含まれていない場合は SecurityException がスローされます。name が null の場合、この判別は実行されません。必ず、定義するクラスのバイナリ名をバイトとともに渡すようにしてください。このようにして渡すと、定義するクラスは実際に考えたとおりのクラスになります。
「java.*」パッケージのすべてのクラスはブートストラップクラスローダーでしか定義できないので、「java.」で始まる name を指定することはできません。name が null でない場合、それは、バイト配列「b」で指定されるクラスのバイナリ名と等しくなければいけません。そうでないと、NoClassDefFoundError がスローされます。
name
- クラスの予想されるバイナリ名。不明な場合は nullb
- クラスデータを構成するバイト。off から off+len-1 までの位置にある byte は、『Java™ 仮想マシン仕様』で定義される有効なクラスファイルの形式を持つoff
- クラスデータの b 内での開始オフセットlen
- クラスデータの長さprotectionDomain
- このクラスの ProtectionDomainClassFormatError
- データが有効なクラスを含まなかった場合NoClassDefFoundError
- name が、b で指定されたクラスのバイナリ名に等しくない場合IndexOutOfBoundsException
- off または len が負の場合、または off+len が b.length より大きい場合SecurityException
- このクラスとは異なる証明書セットを使って署名されたクラスを含むパッケージに、このクラスを追加しようとする場合、または name が「java.」で始まる場合。protected final Class<?> defineClass(String name, ByteBuffer b, ProtectionDomain protectionDomain) throws ClassFormatError
ByteBuffer
をクラス Class のインスタンスに変換します。ドメインが null の場合、defineClass(String, byte[], int, int)
のドキュメントで指定されているように、デフォルトドメインがクラスに割り当てられます。最初にクラスを解決してからでなければ、クラスを使用することはできません。
パッケージの証明書のセットを決定しているパッケージで定義された最初のクラスに関する規則と、クラス名での制約は、defineClass(String, byte[], int, int, ProtectionDomain)
のドキュメントで指定されているものと同等です。
このメソッドを cl.defineClass(name, bBuffer, pd) の形式で呼び出すと、次の文とまったく同じ結果が得られます
...
byte[] temp = new byte[bBuffer.remaining
()];
bBuffer.get
(temp);
returncl.defineClass(name, temp, 0, temp.length, pd);
name
- クラスの予想されるバイナリ名。不明な場合は nullb
- クラスデータを構成するバイト。b.position() から b.position() + b.limit() -1 までの位置にある byte は、『Java™ 仮想マシン仕様』で定義される有効なクラスファイルの形式を持つ。protectionDomain
- このクラスの ProtectionDomain、または null。ClassFormatError
- データが有効なクラスを含まなかった場合。NoClassDefFoundError
- name が、b で指定されたクラスのバイナリ名に等しくない場合SecurityException
- このクラスとは異なる証明書セットを使って署名されたクラスを含むパッケージに、このクラスを追加しようとする場合、または name が「java.」で始まる場合。defineClass(String, byte[], int, int, ProtectionDomain)
protected final void resolveClass(Class<?> c)
c
- リンクするクラスNullPointerException
- c が null の場合。defineClass(String, byte[], int, int)
protected final Class<?> findSystemClass(String name) throws ClassNotFoundException
このメソッドはシステムクラスローダー (getSystemClassLoader()
を参照) を使ってクラスをロードします。返される Class オブジェクトは、そのオブジェクトに関連付けられた ClassLoader を 1 つ以上持つ場合があります。ClassLoader のサブクラスでは通常、このメソッドを呼び出す必要はありません。これは、ほとんどのクラスローダーでは findClass(String)
だけをオーバーライドすればよいからです。
name
- クラスのバイナリ名ClassNotFoundException
- クラスが見つからなかった場合ClassLoader(ClassLoader)
, getParent()
protected final Class<?> findLoadedClass(String name)
name
- クラスのバイナリ名protected final void setSigners(Class<?> c, Object[] signers)
c
- Class オブジェクトsigners
- クラスの署名者public URL getResource(String name)
リソースの名前は、「/」で区切られたパス名であり、これによってリソースが識別されます。
このメソッドは、まずリソースの親クラスローダーを検索します。親が null の場合、仮想マシンに組み込まれたクラスローダーのパスが検索されます。それに失敗すると、このメソッドはリソースを見つけるために findResource(String)
を呼び出します。
name
- リソース名public Enumeration<URL> getResources(String name) throws IOException
リソースの名前は、/ で区切られたパス名であり、これによってリソースが識別されます。
検索順については、getResource(String)
のドキュメントを参照してください。
name
- リソース名URL
オブジェクトの列挙。リソースが見つからなかった場合、列挙は空になる。クラスローダーがアクセスできないリソースは列挙に入らないIOException
- 入出力エラーが発生した場合findResources(String)
protected URL findResource(String name)
name
- リソース名protected Enumeration<URL> findResources(String name) throws IOException
URL
オブジェクトの列挙を返します。クラスローダーの実装は、リソースのロード元を特定するためにこのメソッドをオーバーライドします。 name
- リソース名URL
オブジェクトの列挙IOException
- 入出力エラーが発生した場合protected static boolean registerAsParallelCapable()
public static URL getSystemResource(String name)
getSystemClassLoader()
を参照) を使ってリソースを見つけます。 name
- リソース名URL
オブジェクト。リソースが見つからなかった場合は nullpublic static Enumeration<URL> getSystemResources(String name) throws IOException
URL
オブジェクトの Enumeration
として返されます。
検索順については、getSystemResource(String)
のドキュメントを参照してください。
name
- リソース名URL
オブジェクトの列挙IOException
- 入出力エラーが発生した場合public InputStream getResourceAsStream(String name)
検索順については、getResource(String)
のドキュメントを参照してください。
name
- リソース名public static InputStream getSystemResourceAsStream(String name)
getSystemClassLoader()
を参照) を使ってリソースを見つけます。 name
- リソース名public final ClassLoader getParent()
セキュリティーマネージャーが存在する場合、呼び出し側のクラスローダーが null でなく、このクラスローダーの祖先でもない場合は、このメソッドは RuntimePermission("getClassLoader")
アクセス権を使ってセキュリティーマネージャーの checkPermission
メソッドを呼び出すことによって、親クラスローダーへのアクセスが許可されていることを確認します。そうでない場合は、SecurityException がスローされます。
SecurityException
- セキュリティーマネージャーが存在し、その checkPermission メソッドがこのクラスローダーの親クラスローダーへのアクセスを許可しない場合。public static ClassLoader getSystemClassLoader()
このメソッドが最初に呼び出されるのは、実行時の起動シーケンスの初期です。この時点で、メソッドはシステムクラスローダーを作成し、呼び出す Thread のコンテキストクラスローダーにそれを設定します。
デフォルトのシステムクラスローダーは、このクラスの実装依存インスタンスです。
このメソッドの最初の呼び出し時に、システムプロパティー「java.system.class.loader」が定義される場合、このプロパティーの値がシステムクラスローダーとして返されるクラスの名前になります。このクラスは、デフォルトのシステムクラスローダーを使用してロードされます。また、このクラスは、委譲の親として使用される、ClassLoader 型の単一のパラメータを取る public コンストラクタを定義する必要があります。次に、このコンストラクタを使用し、デフォルトのシステムクラスローダーをパラメータに指定して、インスタンスが作成されます。結果として得られるクラスローダーは、システムクラスローダーとして定義されます。
セキュリティーマネージャーが存在し、呼び出し元のクラスローダーが null でなく、かつ呼び出し元のクラスローダーがシステムクラスローダーと同じでもその祖先でもない場合、このメソッドは、セキュリティーマネージャーの checkPermission
メソッドを RuntimePermission("getClassLoader")
アクセス権で呼び出すことで、システムクラスローダーへのアクセスを確認します。そうでない場合は、SecurityException がスローされます。
SecurityException
- セキュリティーマネージャーが存在し、その checkPermission メソッドがこのシステムクラスローダーへのアクセスを許可しない場合。IllegalStateException
- 「java.system.class.loader」プロパティーにより指定されたクラスローダーの構築時に、再帰的に呼び出される場合。Error
- システムプロパティー「java.system.class.loader」は定義されるが、名前付きクラスをロードできない場合、プロバイダクラスは必須コンストラクタを定義しないか、その呼び出し時に例外がスローされる。エラーの根本原因は、Throwable.getCause()
メソッドを使用して取得できる。protected Package definePackage(String name, String specTitle, String specVersion, String specVendor, String implTitle, String implVersion, String implVendor, URL sealBase) throws IllegalArgumentException
name
- パッケージ名specTitle
- 仕様のタイトルspecVersion
- 仕様のバージョンspecVendor
- 仕様のベンダーimplTitle
- 実装のタイトルimplVersion
- 実装のバージョンimplVendor
- 実装のベンダーsealBase
- null でない場合、このパッケージは指定されたコードソース URL
オブジェクトに対してシールされる。そうでない場合、パッケージはシールされないIllegalArgumentException
- パッケージ名が、このクラスローダーかまたはその祖先の 1 つに存在するパッケージと重複する場合protected Package getPackage(String name)
name
- パッケージ名protected Package[] getPackages()
protected String findLibrary(String libname)
libname
- ライブラリ名System.loadLibrary(String)
, System.mapLibraryName(String)
public void setDefaultAssertionStatus(boolean enabled)
setPackageAssertionStatus(String, boolean)
または setClassAssertionStatus(String, boolean)
を呼び出します。 enabled
- このクラスローダーによりロードされるクラスのアサーションが、デフォルトで有効な場合は true、デフォルトで無効な場合は false。public void setPackageAssertionStatus(String packageName, boolean enabled)
p という名前のパッケージのサブパッケージは、すべて名前が「p.」で始まります。たとえば、javax.swing.text は javax.swing のサブパッケージであり、java.util と java.lang.reflect はどちらも java のサブパッケージです。
1 つのクラスに複数のパッケージデフォルトが適用される場合は、そのクラスにもっとも関連性の高いパッケージデフォルトが、ほかのパッケージデフォルトに優先して使用されます。たとえば、javax.lang と javax.lang.reflect の両方にパッケージデフォルトが関連付けられている場合、後者のパッケージデフォルトは javax.lang.reflect 内のクラスに適用されます。
パッケージデフォルトは、クラスローダーのデフォルトのアサーションステータスよりも優先されます。ただし、setClassAssertionStatus(String, boolean)
を呼び出すことで、クラス単位でオーバーライドできます。
packageName
- パッケージデフォルトのアサーションステータスを設定するパッケージ名。null 値は「カレント」である無名パッケージを示す (『Java™ 言語仕様』のセクション 7.4.2 を参照。)enabled
- このクラスローダーによりロードされ、指定されたパッケージまたはそのサブパッケージのどれかに属するクラスが、デフォルトで有効なアサーションを保持する場合は true、デフォルトで無効なアサーションを保持する場合は false。public void setClassAssertionStatus(String className, boolean enabled)
指定されたクラスがトップレベルのクラスではない場合、この呼び出しは、どのクラスのアサーションステータスに対しても影響を与えません。
className
- アサーションステータスを設定するトップレベルのクラスの完全指定クラス名。enabled
- 初期化時に、指定されたクラスでアサーションを有効にする場合は true、アサーションを無効にする場合は false。public void clearAssertionStatus()
バグまたは機能を送信
詳細な API リファレンスおよび開発者ドキュメントについては、Java SE のドキュメントを参照してください。そのドキュメントには、概念的な概要、用語の定義、回避方法、有効なコード例などの、開発者を対象にしたより詳細な説明が含まれています。
Copyright © 1993, 2013, Oracle and/or its affiliates. All rights reserved.