This commit is contained in:
Andrew John Hughes 2024-04-17 02:29:16 +00:00
commit 0e0b018acb
17 changed files with 242 additions and 173 deletions

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2013, Red Hat Inc.
* Copyright (c) 2005, 2019, Oracle and/or its affiliates.
* Copyright (c) 2005, 2024, Oracle and/or its affiliates.
* All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -150,8 +150,10 @@ LIR_Address* LIRGenerator::generate_address(LIR_Opr base, LIR_Opr index,
if (index->is_register()) {
// apply the shift and accumulate the displacement
if (shift > 0) {
LIR_Opr tmp = new_pointer_register();
__ shift_left(index, shift, tmp);
// Use long register to avoid overflow when shifting large index values left.
LIR_Opr tmp = new_register(T_LONG);
__ convert(Bytecodes::_i2l, index, tmp);
__ shift_left(tmp, shift, tmp);
index = tmp;
}
if (disp != 0) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -156,8 +156,10 @@ LIR_Address* LIRGenerator::generate_address(LIR_Opr base, LIR_Opr index,
if (index->is_register()) {
// apply the shift and accumulate the displacement
if (shift > 0) {
LIR_Opr tmp = new_pointer_register();
__ shift_left(index, shift, tmp);
// Use long register to avoid overflow when shifting large index values left.
LIR_Opr tmp = new_register(T_LONG);
__ convert(Bytecodes::_i2l, index, tmp);
__ shift_left(tmp, shift, tmp);
index = tmp;
}
if (disp != 0) {

View File

@ -1235,14 +1235,13 @@ oop java_lang_Throwable::message(Handle throwable) {
}
// Return Symbol for detailed_message or NULL
Symbol* java_lang_Throwable::detail_message(oop throwable) {
PRESERVE_EXCEPTION_MARK; // Keep original exception
oop detailed_message = java_lang_Throwable::message(throwable);
if (detailed_message != NULL) {
return java_lang_String::as_symbol(detailed_message, THREAD);
const char* java_lang_Throwable::message_as_utf8(oop throwable) {
oop msg = java_lang_Throwable::message(throwable);
const char* msg_utf8 = NULL;
if (msg != NULL) {
msg_utf8 = java_lang_String::as_utf8_string(msg);
}
return NULL;
return msg_utf8;
}
void java_lang_Throwable::set_message(oop throwable, oop value) {

View File

@ -523,12 +523,12 @@ class java_lang_Throwable: AllStatic {
static void set_backtrace(oop throwable, oop value);
// Needed by JVMTI to filter out this internal field.
static int get_backtrace_offset() { return backtrace_offset;}
static int get_detailMessage_offset() { return detailMessage_offset;}
// Message
static int get_detailMessage_offset() { return detailMessage_offset;}
static oop message(oop throwable);
static oop message(Handle throwable);
static const char* message_as_utf8(oop throwable);
static void set_message(oop throwable, oop value);
static Symbol* detail_message(oop throwable);
static void print_stack_element(outputStream *st, Handle mirror, int method,
int version, int bci, int cpref);
static void print_stack_element(outputStream *st, methodHandle method, int bci);

View File

@ -33,7 +33,7 @@
// add new entry to the table
void ResolutionErrorTable::add_entry(int index, unsigned int hash,
constantPoolHandle pool, int cp_index,
Symbol* error, Symbol* message)
Symbol* error, const char* message)
{
assert_locked_or_safepoint(SystemDictionary_lock);
assert(!pool.is_null() && error != NULL, "adding NULL obj");
@ -64,16 +64,14 @@ void ResolutionErrorEntry::set_error(Symbol* e) {
_error->increment_refcount();
}
void ResolutionErrorEntry::set_message(Symbol* c) {
assert(c != NULL, "must set a value");
_message = c;
_message->increment_refcount();
void ResolutionErrorEntry::set_message(const char* c) {
_message = c != NULL ? os::strdup(c) : NULL;
}
// create new error entry
ResolutionErrorEntry* ResolutionErrorTable::new_entry(int hash, ConstantPool* pool,
int cp_index, Symbol* error,
Symbol* message)
const char* message)
{
ResolutionErrorEntry* entry = (ResolutionErrorEntry*)Hashtable<ConstantPool*, mtClass>::new_entry(hash, pool);
entry->set_cp_index(cp_index);
@ -87,7 +85,9 @@ void ResolutionErrorTable::free_entry(ResolutionErrorEntry *entry) {
// decrement error refcount
assert(entry->error() != NULL, "error should be set");
entry->error()->decrement_refcount();
entry->message()->decrement_refcount();
if (entry->message() != NULL) {
FREE_C_HEAP_ARRAY(char, entry->message(), mtInternal);
}
Hashtable<ConstantPool*, mtClass>::free_entry(entry);
}

View File

@ -39,7 +39,7 @@ public:
ResolutionErrorTable(int table_size);
ResolutionErrorEntry* new_entry(int hash, ConstantPool* pool, int cp_index,
Symbol* error, Symbol* message);
Symbol* error, const char* message);
void free_entry(ResolutionErrorEntry *entry);
ResolutionErrorEntry* bucket(int i) {
@ -56,7 +56,7 @@ public:
}
void add_entry(int index, unsigned int hash,
constantPoolHandle pool, int which, Symbol* error, Symbol* message);
constantPoolHandle pool, int cp_index, Symbol* error, const char* error_msg);
// find error given the constant pool and constant pool index
@ -80,7 +80,7 @@ class ResolutionErrorEntry : public HashtableEntry<ConstantPool*, mtClass> {
private:
int _cp_index;
Symbol* _error;
Symbol* _message;
const char* _message;
public:
ConstantPool* pool() const { return literal(); }
@ -91,8 +91,9 @@ class ResolutionErrorEntry : public HashtableEntry<ConstantPool*, mtClass> {
Symbol* error() const { return _error; }
void set_error(Symbol* e);
Symbol* message() const { return _message; }
void set_message(Symbol* c);
const char* message() const { return _message; }
// The incoming message is copied to the C-Heap.
void set_message(const char* c);
ResolutionErrorEntry* next() const {
return (ResolutionErrorEntry*)HashtableEntry<ConstantPool*, mtClass>::next();

View File

@ -2280,7 +2280,7 @@ bool SystemDictionary::add_loader_constraint(Symbol* class_name,
// Add entry to resolution error table to record the error when the first
// attempt to resolve a reference to a class has failed.
void SystemDictionary::add_resolution_error(constantPoolHandle pool, int which,
Symbol* error, Symbol* message) {
Symbol* error, const char* message) {
unsigned int hash = resolution_errors()->compute_hash(pool, which);
int index = resolution_errors()->hash_to_index(hash);
{
@ -2296,7 +2296,7 @@ void SystemDictionary::delete_resolution_error(ConstantPool* pool) {
// Lookup resolution error table. Returns error if found, otherwise NULL.
Symbol* SystemDictionary::find_resolution_error(constantPoolHandle pool, int which,
Symbol** message) {
const char** message) {
unsigned int hash = resolution_errors()->compute_hash(pool, which);
int index = resolution_errors()->hash_to_index(hash);
{

View File

@ -549,10 +549,10 @@ public:
// Record the error when the first attempt to resolve a reference from a constant
// pool entry to a class fails.
static void add_resolution_error(constantPoolHandle pool, int which, Symbol* error,
Symbol* message);
const char* message);
static void delete_resolution_error(ConstantPool* pool);
static Symbol* find_resolution_error(constantPoolHandle pool, int which,
Symbol** message);
const char** message);
protected:

View File

@ -451,11 +451,11 @@ IRT_ENTRY(address, InterpreterRuntime::exception_handler_for_exception(JavaThrea
// tracing
if (TraceExceptions) {
ResourceMark rm(thread);
Symbol* message = java_lang_Throwable::detail_message(h_exception());
const char* detail_message = java_lang_Throwable::message_as_utf8(h_exception());
ttyLocker ttyl; // Lock after getting the detail message
if (message != NULL) {
if (detail_message != NULL) {
tty->print_cr("Exception <%s: %s> (" INTPTR_FORMAT ")",
h_exception->print_value_string(), message->as_C_string(),
h_exception->print_value_string(), detail_message,
(address)h_exception());
} else {
tty->print_cr("Exception <%s> (" INTPTR_FORMAT ")",

View File

@ -569,13 +569,16 @@ bool ConstantPool::resolve_class_constants(TRAPS) {
return true;
}
Symbol* ConstantPool::exception_message(constantPoolHandle this_oop, int which, constantTag tag, oop pending_exception) {
const char* ConstantPool::exception_message(constantPoolHandle this_oop, int which, constantTag tag, oop pending_exception) {
// Note: caller needs ResourceMark
// Dig out the detailed message to reuse if possible
Symbol* message = java_lang_Throwable::detail_message(pending_exception);
if (message != NULL) {
return message;
const char* msg = java_lang_Throwable::message_as_utf8(pending_exception);
if (msg != NULL) {
return msg;
}
Symbol* message = NULL;
// Return specific message for the tag
switch (tag.value()) {
case JVM_CONSTANT_UnresolvedClass:
@ -594,16 +597,16 @@ Symbol* ConstantPool::exception_message(constantPoolHandle this_oop, int which,
ShouldNotReachHere();
}
return message;
return message != NULL ? message->as_C_string() : NULL;
}
void ConstantPool::throw_resolution_error(constantPoolHandle this_oop, int which, TRAPS) {
Symbol* message = NULL;
ResourceMark rm(THREAD);
const char* message = NULL;
Symbol* error = SystemDictionary::find_resolution_error(this_oop, which, &message);
assert(error != NULL && message != NULL, "checking");
CLEAR_PENDING_EXCEPTION;
ResourceMark rm;
THROW_MSG(error, message->as_C_string());
THROW_MSG(error, message);
}
// If resolution for Class, MethodHandle or MethodType fails, save the exception
@ -622,7 +625,9 @@ void ConstantPool::save_and_throw_exception(constantPoolHandle this_oop, int whi
// and OutOfMemoryError, etc, or if the thread was hit by stop()
// Needs clarification to section 5.4.3 of the VM spec (see 6308271)
} else if (this_oop->tag_at(which).value() != error_tag) {
Symbol* message = exception_message(this_oop, which, tag, PENDING_EXCEPTION);
ResourceMark rm(THREAD);
const char* message = exception_message(this_oop, which, tag, PENDING_EXCEPTION);
SystemDictionary::add_resolution_error(this_oop, which, error, message);
this_oop->tag_at_put(which, error_tag);
} else {

View File

@ -830,7 +830,7 @@ class ConstantPool : public Metadata {
// Exception handling
static void throw_resolution_error(constantPoolHandle this_oop, int which, TRAPS);
static Symbol* exception_message(constantPoolHandle this_oop, int which, constantTag tag, oop pending_exception);
static const char* exception_message(constantPoolHandle this_oop, int which, constantTag tag, oop pending_exception);
static void save_and_throw_exception(constantPoolHandle this_oop, int which, constantTag tag, TRAPS);
public:

View File

@ -32,6 +32,8 @@ import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.LinkedList;
import java.util.List;
import java.util.jar.JarOutputStream;
import java.util.jar.Pack200;
import java.util.zip.CRC32;
@ -77,8 +79,13 @@ class NativeUnpack {
private int _estFileLimit; // ditto
private int _prevPercent = -1; // for monotonicity
private final CRC32 _crc32 = new CRC32();
private byte[] _buf = new byte[1<<14];
private final CRC32 _crc32 = new CRC32();
private static final int MAX_BUFFER_SIZE = 1 << 20; // 1 MB byte[]
private byte[] _buf = new byte[1 << 14]; // 16 KB byte[] initially
private List<byte[]> _extra_buf = new LinkedList<>(); // extra buffers
// for large files
private byte[] _current_buf; // buffer being filled
private int _current_buf_pos; // position to fill in more data
private UnpackerImpl _p200;
private PropMap _props;
@ -195,41 +202,44 @@ class NativeUnpack {
updateProgress(); // reset progress bar
for (;;) {
// Read the packed bits.
long counts = start(presetInput, 0);
_byteCount = _estByteLimit = 0; // reset partial scan counts
++_segCount; // just finished scanning a whole segment...
int nextSeg = (int)( counts >>> 32 );
int nextFile = (int)( counts >>> 0 );
long counts = start(presetInput, 0), consumed;
try {
_byteCount = _estByteLimit = 0; // reset partial scan counts
++_segCount; // just finished scanning a whole segment...
int nextSeg = (int) (counts >>> 32);
int nextFile = (int) (counts >>> 0);
// Estimate eventual total number of segments and files.
_estSegLimit = _segCount + nextSeg;
double filesAfterThisSeg = _fileCount + nextFile;
_estFileLimit = (int)( (filesAfterThisSeg *
_estSegLimit) / _segCount );
// Estimate eventual total number of segments and files.
_estSegLimit = _segCount + nextSeg;
double filesAfterThisSeg = _fileCount + nextFile;
_estFileLimit = (int) ((filesAfterThisSeg *
_estSegLimit) / _segCount);
// Write the files.
int[] intParts = { 0,0, 0, 0 };
// intParts = {size.hi/lo, mod, defl}
Object[] parts = { intParts, null, null, null };
// parts = { {intParts}, name, data0/1 }
while (getNextFile(parts)) {
//BandStructure.printArrayTo(System.out, intParts, 0, parts.length);
String name = (String) parts[1];
long size = ( (long)intParts[0] << 32)
+ (((long)intParts[1] << 32) >>> 32);
// Write the files.
int[] intParts = {0, 0, 0, 0};
// intParts = {size.hi/lo, mod, defl}
Object[] parts = {intParts, null, null, null};
// parts = { {intParts}, name, data0/1 }
while (getNextFile(parts)) {
//BandStructure.printArrayTo(System.out, intParts, 0, parts.length);
String name = (String) parts[1];
long size = ((long) intParts[0] << 32)
+ (((long) intParts[1] << 32) >>> 32);
long mtime = (modtime != Constants.NO_MODTIME ) ?
modtime : intParts[2] ;
boolean deflateHint = (intParts[3] != 0);
ByteBuffer data0 = (ByteBuffer) parts[2];
ByteBuffer data1 = (ByteBuffer) parts[3];
writeEntry(jstream, name, mtime, size, deflateHint,
data0, data1);
++_fileCount;
updateProgress();
long mtime = (modtime != Constants.NO_MODTIME) ?
modtime : intParts[2];
boolean deflateHint = (intParts[3] != 0);
ByteBuffer data0 = (ByteBuffer) parts[2];
ByteBuffer data1 = (ByteBuffer) parts[3];
writeEntry(jstream, name, mtime, size, deflateHint,
data0, data1);
++_fileCount;
updateProgress();
}
presetInput = getUnusedInput();
} finally {
consumed = finish();
}
presetInput = getUnusedInput();
long consumed = finish();
if (_verbose > 0)
Utils.log.info("bytes consumed = "+consumed);
if (presetInput == null &&
@ -256,76 +266,145 @@ class NativeUnpack {
// Note: caller is responsible to finish with jstream.
}
private void writeEntry(JarOutputStream j, String name,
long mtime, long lsize, boolean deflateHint,
ByteBuffer data0, ByteBuffer data1) throws IOException {
int size = (int)lsize;
if (size != lsize)
throw new IOException("file too large: "+lsize);
CRC32 crc32 = _crc32;
if (_verbose > 1)
Utils.log.fine("Writing entry: "+name+" size="+size
+(deflateHint?" deflated":""));
if (_buf.length < size) {
int newSize = size;
while (newSize < _buf.length) {
newSize <<= 1;
if (newSize <= 0) {
newSize = size;
break;
}
}
_buf = new byte[newSize];
private void writeEntry(JarOutputStream j, String name, long mtime,
long lsize, boolean deflateHint, ByteBuffer data0,
ByteBuffer data1) throws IOException {
if (lsize < 0 || lsize > Integer.MAX_VALUE) {
throw new IOException("file too large: " + lsize);
}
assert(_buf.length >= size);
int size = (int) lsize;
int fillp = 0;
if (data0 != null) {
int size0 = data0.capacity();
data0.get(_buf, fillp, size0);
fillp += size0;
}
if (data1 != null) {
int size1 = data1.capacity();
data1.get(_buf, fillp, size1);
fillp += size1;
}
while (fillp < size) {
// Fill in rest of data from the stream itself.
int nr = in.read(_buf, fillp, size - fillp);
if (nr <= 0) throw new IOException("EOF at end of archive");
fillp += nr;
if (_verbose > 1) {
Utils.log.fine("Writing entry: " + name + " size=" + size +
(deflateHint ? " deflated" : ""));
}
ZipEntry z = new ZipEntry(name);
z.setTime(mtime * 1000);
z.setSize(size);
if (size == 0) {
z.setMethod(ZipOutputStream.STORED);
z.setSize(0);
z.setCompressedSize(size);
z.setCrc(0);
z.setCompressedSize(0);
j.putNextEntry(z);
} else if (!deflateHint) {
z.setMethod(ZipOutputStream.STORED);
z.setSize(size);
z.setCompressedSize(size);
crc32.reset();
crc32.update(_buf, 0, size);
z.setCrc(crc32.getValue());
writeEntryData(j, z, data0, data1, size, true);
} else {
z.setMethod(Deflater.DEFLATED);
z.setSize(size);
writeEntryData(j, z, data0, data1, size, false);
}
j.putNextEntry(z);
if (size > 0)
j.write(_buf, 0, size);
j.closeEntry();
if (_verbose > 0) Utils.log.info("Writing " + Utils.zeString(z));
}
private void writeEntryData(JarOutputStream j, ZipEntry z, ByteBuffer data0,
ByteBuffer data1, int size, boolean computeCrc32)
throws IOException {
prepareReadBuffers(size);
try {
int inBytes = size;
inBytes -= readDataByteBuffer(data0);
inBytes -= readDataByteBuffer(data1);
inBytes -= readDataInputStream(inBytes);
if (inBytes != 0L) {
throw new IOException("invalid size: " + size);
}
if (computeCrc32) {
_crc32.reset();
processReadData((byte[] buff, int offset, int len) -> {
_crc32.update(buff, offset, len);
});
z.setCrc(_crc32.getValue());
}
j.putNextEntry(z);
processReadData((byte[] buff, int offset, int len) -> {
j.write(buff, offset, len);
});
} finally {
resetReadBuffers();
}
}
private void prepareReadBuffers(int size) {
if (_buf.length < size && _buf.length < MAX_BUFFER_SIZE) {
// Grow the regular buffer to accomodate lsize up to a limit.
long newIdealSize = _buf.length;
while (newIdealSize < size && newIdealSize < MAX_BUFFER_SIZE) {
// Never overflows: size is [0, 0x7FFFFFFF].
newIdealSize <<= 1;
}
int newSize = (int) Long.min(newIdealSize, MAX_BUFFER_SIZE);
_buf = new byte[newSize];
}
resetReadBuffers();
}
private void resetReadBuffers() {
_extra_buf.clear();
_current_buf = _buf;
_current_buf_pos = 0;
}
private int readDataByteBuffer(ByteBuffer data) throws IOException {
if (data == null) {
return 0;
}
return readData(data.remaining(),
(byte[] buff, int offset, int len) -> {
data.get(buff, offset, len);
return len;
});
}
private int readDataInputStream(int inBytes) throws IOException {
return readData(inBytes, (byte[] buff, int offset, int len) -> {
return in.read(buff, offset, len);
});
}
private static interface ReadDataCB {
public int read(byte[] buff, int offset, int len) throws IOException;
}
private int readData(int bytesToRead, ReadDataCB readDataCb)
throws IOException {
int bytesRemaining = bytesToRead;
while (bytesRemaining > 0) {
if (_current_buf_pos == _current_buf.length) {
byte[] newBuff = new byte[Integer.min(bytesRemaining,
MAX_BUFFER_SIZE)];
_extra_buf.add(newBuff);
_current_buf = newBuff;
_current_buf_pos = 0;
}
int current_buffer_space = _current_buf.length - _current_buf_pos;
int nextRead = Integer.min(current_buffer_space, bytesRemaining);
int bytesRead = readDataCb.read(_current_buf, _current_buf_pos,
nextRead);
if (bytesRead <= 0) {
throw new IOException("EOF at end of archive");
}
_current_buf_pos += bytesRead;
bytesRemaining -= bytesRead;
}
return bytesToRead - bytesRemaining;
}
private static interface ProcessDataCB {
public void apply(byte[] buff, int offset, int len) throws IOException;
}
private void processReadData(ProcessDataCB processDataCB)
throws IOException {
processDataCB.apply(_buf, 0, _buf == _current_buf ? _current_buf_pos :
_buf.length);
for (byte[] buff : _extra_buf) {
// Extra buffers are allocated of a size such that they are always
// full, including the last one.
processDataCB.apply(buff, 0, buff.length);
};
}
}

View File

@ -247,14 +247,6 @@ public final class RSAPrivateCrtKeyImpl
return keyParams;
}
// return a string representation of this key for debugging
@Override
public String toString() {
return "SunRsaSign " + getAlgorithm() + " private CRT key, " + n.bitLength()
+ " bits" + "\n params: " + keyParams + "\n modulus: " + n
+ "\n private exponent: " + d;
}
/**
* Parse the key. Called by PKCS8Key.
*/

View File

@ -123,14 +123,6 @@ public final class RSAPrivateKeyImpl extends PKCS8Key implements RSAPrivateKey {
return keyParams;
}
// return a string representation of this key for debugging
@Override
public String toString() {
return "Sun " + getAlgorithm() + " private key, " + n.bitLength()
+ " bits" + "\n params: " + keyParams + "\n modulus: " + n
+ "\n private exponent: " + d;
}
/**
* Restores the state of this object from the stream.
* <p>

View File

@ -76,10 +76,14 @@ abstract class CKey implements Key, Length {
protected final String algorithm;
protected CKey(String algorithm, NativeHandles handles, int keyLength) {
private final boolean isPublic;
protected CKey(String algorithm, NativeHandles handles, int keyLength,
boolean isPublic) {
this.algorithm = algorithm;
this.handles = handles;
this.keyLength = keyLength;
this.isPublic = isPublic;
}
// Native method to cleanup the key handle.
@ -102,6 +106,18 @@ abstract class CKey implements Key, Length {
return algorithm;
}
public String toString() {
String typeStr;
if (handles.hCryptKey != 0) {
typeStr = getKeyType(handles.hCryptKey) + ", container=" +
getContainerName(handles.hCryptProv);
} else {
typeStr = "CNG";
}
return algorithm + " " + (isPublic ? "PublicKey" : "PrivateKey") +
" [size=" + keyLength + " bits, type=" + typeStr + "]";
}
protected native static String getContainerName(long hCryptProv);
protected native static String getKeyType(long hCryptKey);

View File

@ -41,7 +41,7 @@ class CPrivateKey extends CKey implements PrivateKey {
private static final long serialVersionUID = 8113152807912338063L;
private CPrivateKey(String alg, NativeHandles handles, int keyLength) {
super(alg, handles, keyLength);
super(alg, handles, keyLength, false);
}
// Called by native code inside security.cpp
@ -64,16 +64,6 @@ class CPrivateKey extends CKey implements PrivateKey {
return null;
}
public String toString() {
if (handles.hCryptKey != 0) {
return algorithm + "PrivateKey [size=" + keyLength + " bits, type=" +
getKeyType(handles.hCryptKey) + ", container=" +
getContainerName(handles.hCryptProv) + "]";
} else {
return algorithm + "PrivateKey [size=" + keyLength + " bits, type=CNG]";
}
}
// This class is not serializable
private void writeObject(java.io.ObjectOutputStream out)
throws java.io.IOException {

View File

@ -110,9 +110,8 @@ public abstract class CPublicKey extends CKey implements PublicKey {
}
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append(algorithm).append("PublicKey [size=").append(keyLength)
.append("]\n ECPoint: ").append(getW())
StringBuffer sb = new StringBuffer(super.toString());
sb.append("\n ECPoint: ").append(getW())
.append("\n params: ").append(getParams());
return sb.toString();
}
@ -129,16 +128,8 @@ public abstract class CPublicKey extends CKey implements PublicKey {
}
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append(algorithm).append("PublicKey [size=").append(keyLength)
.append(" bits, type=");
if (handles.hCryptKey != 0) {
sb.append(getKeyType(handles.hCryptKey))
.append(", container=").append(getContainerName(handles.hCryptProv));
} else {
sb.append("CNG");
}
sb.append("]\n modulus: ").append(getModulus())
StringBuffer sb = new StringBuffer(super.toString());
sb.append("\n modulus: ").append(getModulus())
.append("\n public exponent: ").append(getPublicExponent());
return sb.toString();
}
@ -209,7 +200,7 @@ public abstract class CPublicKey extends CKey implements PublicKey {
protected CPublicKey(
String alg, NativeHandles handles, int keyLength) {
super(alg, handles, keyLength);
super(alg, handles, keyLength, true);
}
@Override