Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Work-in-Progress on PL/Java refactoring, API modernization #399

Open
wants to merge 120 commits into
base: REL1_7_STABLE
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
120 commits
Select commit Hold shift + click to select a range
580b25a
Easy warmup: less JNI in Invocation
jcflack Jan 23, 2022
17a3a26
These two lines considered redundant
jcflack Jan 23, 2022
9342f68
Tests for use of upper memory context
jcflack Jan 23, 2022
b2094ba
Add switchToUpperContext for non-composite SRFs
jcflack Jan 23, 2022
e441724
Use SPI in the purely nested fashion it expects
jcflack Jan 23, 2022
e380e6b
Add a nested/SPI test to SetOfRecordTest
jcflack Jan 23, 2022
2d54359
Also eliminate special SRF Invocation treatment
jcflack Jan 23, 2022
d2b920b
Merge Invocation/set-returning-function rework
jcflack Jan 23, 2022
41eb615
Two caching tools: CacheMap and SwitchPointCache
jcflack Jan 23, 2022
7655fde
Adapter and org.postgresql.pljava.adt.spi package
jcflack Jan 23, 2022
b35c65a
Package org.postgresql.pljava.adt: contracts
jcflack Jan 23, 2022
7786fbf
CharsetEncoding, CatalogObject, and a few more
jcflack Jan 23, 2022
42805b1
Add enough implementation for CharsetEncoding use
jcflack Jan 23, 2022
712f5d2
Expose MemoryContext and ResourceOwner in Java
jcflack Jan 23, 2022
5a9cdf9
Begin MemoryContext/ResourceOwner implementation
jcflack Jan 23, 2022
f387648
Fix an old PgSavepoint bug
jcflack Jan 23, 2022
169b5dc
Now an Invocation is also a Lifespan
jcflack Jan 23, 2022
f7561df
DualState clients that pass no Lifespan
jcflack Jan 23, 2022
6ba4e66
Clients using Invocation.current as Lifespan
jcflack Jan 23, 2022
901712a
Client using its own ResourceOwner as Lifespan
jcflack Jan 23, 2022
827f2d6
Client with both ResourceOwner and MemoryContext
jcflack Jan 23, 2022
349c3e8
Eliminate last use of DualState.Key
jcflack Jan 23, 2022
ea86c77
Merge MemoryContext/ResourceOwner API and uses
jcflack Jan 23, 2022
fc9bd9c
Adapt SQLXMLImpl to be creatable from Java
jcflack Jan 23, 2022
a0269b8
Build out the TupleDescriptor implementation
jcflack Jan 23, 2022
1f17675
Build out TupleTableSlot implementation
jcflack Jan 23, 2022
2e74a6b
Build out the CatalogObject implementation
jcflack Jan 23, 2022
a4656f5
RegClass and RegType have a special relationship
jcflack Jan 23, 2022
e742fae
Attribute, naturally, has complications
jcflack Jan 23, 2022
5adf2c8
Selectively invalidate RegClass and RegType
jcflack Jan 23, 2022
33530b5
Here's a simple complete one, a Database object
jcflack Jan 23, 2022
7ffea74
The rest is straight implementation
jcflack Jan 23, 2022
8ce2c87
A test jig that's been used during development
jcflack Jan 23, 2022
4a773cd
A couple straggling RegType methods
jcflack Jan 23, 2022
9a833d2
Spotted a copy-pasto in an assertion message
jcflack Jan 23, 2022
62d3694
Fix copyright years that were wrong as committed
jcflack Jan 31, 2022
4fa6a19
Pacify AppVeyor
jcflack Jan 31, 2022
f135135
Update straggling currentInvocation checks
jcflack Jan 31, 2022
0b0e4de
Missing initializer caught by MacOS clang
jcflack Jan 31, 2022
04431c4
Look for a way to confirm ARR_DIMS under clang
jcflack Jan 31, 2022
a9f24a9
Give up static check of OFFSET_ArrayType_DIMS
jcflack Jan 31, 2022
cf2f8c5
See if clang permits sizeof *ARR_DIMS(0)
jcflack Jan 31, 2022
13547a9
More work on array adapters
jcflack Feb 1, 2022
4bf4a8d
Some polishing of javadocs and code
jcflack Feb 1, 2022
8140b01
Merge REL1_7_STABLE into feature/REL1_7_STABLE/model
jcflack Jun 14, 2023
e55625e
New ACL rights appear in PG 15 and in 16
jcflack Jun 14, 2023
b0b198d
Whitespace only
jcflack Jun 14, 2023
52acfdf
Numeric typmods change in PG 15
jcflack Jun 14, 2023
acdbb2b
Fix example in AbstractType javadoc
jcflack Jul 31, 2023
101ae01
Additions to AbstractType
jcflack Jul 31, 2023
c7e9ae1
Add methods to Adapter to derive multiarrays
jcflack Jul 31, 2023
45830da
Add ArrayBuilder.build() and a suitable service
jcflack Jul 31, 2023
ff9768b
Implement the multi-array building
jcflack Jul 31, 2023
ecccd54
Consolidate the temporary test jig methods
jcflack Jul 31, 2023
1423366
Add an example for multi-array retrieval
jcflack Jul 31, 2023
87d9389
Add example of a composing Adapter
jcflack Jul 31, 2023
b1b7d13
Another composing adapter, of reference type
jcflack Jul 31, 2023
4147308
A subtlety with canFetchNull is worth mentioning
jcflack Jul 31, 2023
536e87f
Show autoboxing in Adapter composition
jcflack Aug 1, 2023
3db8e54
Tidy up that example SQL query
jcflack Aug 1, 2023
299b69f
No, canFetchNull is not that subtle after all
jcflack Aug 1, 2023
8cbc383
Example didn't demonstrate null long case
jcflack Aug 2, 2023
79a8569
Add PG_VERSION_NUM to ModelConstants
jcflack Aug 3, 2023
716eac5
Let formObjectId accept a version predicate
jcflack Aug 3, 2023
3887c05
Fix an unchecked warning in array service
jcflack Aug 12, 2023
786d546
Javadoc: typos in MultiArray, tweaks in Adapter
jcflack Aug 12, 2023
566edcb
Get rid of "throws SQLException" on tts.get
jcflack Aug 15, 2023
091d8bc
Enter TargetList and its subinterface, Projection
jcflack Aug 15, 2023
1c96e3a
Start on unwrapping ResultSet as Portal
jcflack Aug 15, 2023
4398724
Muck about with SPI class
jcflack Aug 15, 2023
6ec5627
Add more methods to Portal
jcflack Aug 15, 2023
d8bbd60
Lose temporary testmeSPI stuff
jcflack Aug 15, 2023
9d8e6b7
More notational convenience in DualState
jcflack Aug 15, 2023
d966f7b
Add TupleList to present different kinds of such
jcflack Aug 15, 2023
e299b4c
Update example
jcflack Aug 15, 2023
8a0d912
Decree: applyOver methods can throw SQLException
jcflack Aug 15, 2023
ef1f192
Deprecate old hasty TupleDescriptor methods
jcflack Aug 15, 2023
cb98c80
Add test for CatalogObject class initializations
jcflack Aug 15, 2023
10a18f8
Merge targetlist into feature/REL1_7_STABLE/model
jcflack Aug 15, 2023
630717d
Narrow visibility of CatalogObjectImpl additions
jcflack Aug 15, 2023
a0ce0ea
javadoc: a sterner note about the frankenstream
jcflack Aug 15, 2023
5cfdad8
Javadoc: clarify TupleDescriptor.rowType, intern
jcflack Aug 16, 2023
29bafab
Further tame the frankenstream
jcflack Aug 18, 2023
1fc0be2
Migrate SQLXMLImpl.Readable, VarlenaWrapper->Datum
jcflack Aug 20, 2023
c107f9a
Add a set-returning function example
jcflack Aug 24, 2023
59c0ba9
Upstream has reverted MAINTAIN privilege
jcflack Aug 24, 2023
8a88cbf
Beat down unchecked warnings from Datum migration
jcflack Aug 25, 2023
0391e18
Some more missing Adapters
jcflack Aug 26, 2023
45f965c
A reference NUMERIC -> BigDecimal implementation
jcflack Aug 26, 2023
c4b123f
Comment typos caught after pushing upstream
jcflack Aug 27, 2023
606caf0
Don't mistake SQL for Java
jcflack Aug 29, 2023
5e8fa13
Banish recent unchecked warning
jcflack Sep 8, 2023
e511a12
Allow IDX_... gaps in ModelConstants
jcflack Sep 8, 2023
dc62b4e
Regroup and renumber ModelConstants
jcflack Sep 8, 2023
d1e1db3
Pick up SIZEOF_INT via ModelConstants
jcflack Sep 8, 2023
cb71f38
Rename AttNames.andIf to alsoIf
jcflack Sep 9, 2023
3131af9
Merge branch 'REL1_7_STABLE' into feature/REL1_7_STABLE/model
jcflack Sep 19, 2023
f9acf5e
Quit using paired entry points to pass 'trusted'
jcflack Oct 9, 2023
e5dd9f8
Tidy some uses of currentInvocation->function
jcflack Oct 9, 2023
15997b5
check_function_bodies readable from Java
jcflack Oct 9, 2023
19b3c1a
Sundry fixes to CatalogObject implmementations
jcflack Oct 9, 2023
afec77d
Introduce AbstractNoSplitList
jcflack Oct 9, 2023
7faf6c9
Add Identifier.Simple.None
jcflack Oct 9, 2023
57ed135
Distinguish the polymorphic pseudotypes
jcflack Oct 9, 2023
0d65d2b
Add TupleDescImpl.synthesizeDescriptor
jcflack Oct 9, 2023
a061b4e
Interlude: BitSet <-> PostgreSQL bitmapset
jcflack Oct 9, 2023
95fcf8f
TupleTableSlotImpl.NullableDatum
jcflack Oct 9, 2023
08e2079
More invalidation: two more classes, and TupleDesc
jcflack Oct 9, 2023
1ea5bfa
Flesh out the RegProcedure.Memo idea
jcflack Oct 9, 2023
4567117
Give RegType a 'notional' TupleDescriptor
jcflack Oct 9, 2023
93b250c
Add API methods on RegProcedure and memo
jcflack Oct 9, 2023
7af5e94
Interfaces a PL/Java-based language implements
jcflack Oct 9, 2023
95d4133
Add DualState.SingleDeleteGlobalRefP
jcflack Oct 9, 2023
bcd6185
Now put the implementation under it
jcflack Oct 9, 2023
afaeb88
Add example
jcflack Oct 9, 2023
f6f9c61
Merge polyglot into feature/REL1_7_STABLE/model
jcflack Oct 9, 2023
cbfcd09
Restore pre-PG16 buildability (back to PG 13)
jcflack Oct 9, 2023
c327868
Fix added example for library-name diversity
jcflack Oct 9, 2023
75d93b2
Correct spelling of glot64
jcflack Apr 4, 2024
f072a64
Merge REL1_7_STABLE into feature/REL1_7_STABLE/model
jcflack Apr 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions pljava-api/src/main/java/org/postgresql/pljava/Lifespan.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright (c) 2022 Tada AB and other contributors, as listed below.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the The BSD 3-Clause License
* which accompanies this distribution, and is available at
* http://opensource.org/licenses/BSD-3-Clause
*
* Contributors:
* Chapman Flack
*/
package org.postgresql.pljava;

import org.postgresql.pljava.model.MemoryContext; // javadoc
import org.postgresql.pljava.model.ResourceOwner; // javadoc

/**
* Model of any notional object in PostgreSQL or PL/Java that has a definite
* temporal existence, with a detectable end, and so can be used to scope the
* lifetime of any PL/Java object that has corresponding native resources.
*<p>
* A {@code Lifespan} generalizes over assorted classes that can play that role,
* such as PostgreSQL's {@link ResourceOwner ResourceOwner} and
* {@link MemoryContext MemoryContext}. {@code MemoryContext} may see the most
* use in PL/Java, as the typical reason to scope the lifetime of some PL/Java
* object is that it refers to some allocation of native memory.
*<p>
* The invocation of a PL/Java function is also usefully treated as a resource
* owner. It is reasonable to depend on the objects passed in the function call
* to remain usable as long as the call is on the stack, if no other explicit
* lifespan applies.
*<p>
* Java's incubating foreign function and memory API will bring a
* {@code ResourceScope} object for which some relation to a PL/Java
* {@code Lifespan} can probably be defined.
*<p>
* The history of PostgreSQL <a href=
"https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/utils/mmgr/README;hb=HEAD"
>MemoryContext</a>s
* (the older mechanism, appearing in PostgreSQL 7.1), and <a href=
"https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/utils/resowner/README;hb=HEAD"
>ResourceOwner</a>s
* (introduced in 8.0) is interesting. As the latter's {@code README} puts it,
* <q>The design of the ResourceOwner API is modeled on our MemoryContext API,
* which has proven very flexible and successful ... It is tempting to consider
* unifying ResourceOwners and MemoryContexts into a single object type, but
* their usage patterns are sufficiently different ...."</q>
*<p>
* Only later, in PostgreSQL 9.5, did {@code MemoryContext} gain a callback
* mechanism for detecting reset or delete, with which it also becomes usable
* as a kind of lifespan under PL/Java's broadened view of the concept.
* While not <q>unifying ResourceOwners and MemoryContexts into a single
* object type</q>, PL/Java here makes them both available as subtypes of a
* common interface, so either can be chosen to place an appropriate temporal
* scope on a PL/Java object.
*/
public interface Lifespan
{
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,5 @@ public interface Attribute
RegClass CLASS = formObjectId(RegClass.CLASSID, AttributeRelationId);

RegType type();
short length();
}
Original file line number Diff line number Diff line change
Expand Up @@ -551,5 +551,47 @@ RegClass.Known<T> formClassIdImpl(
protected static final int DEFAULT_COLLATION_OID = 100;
protected static final int C_COLLATION_OID = 950;
protected static final int POSIX_COLLATION_OID = 951;

/*
* These magic numbers are assigned here to allow the various well-known
* PostgreSQL ResourceOwners to be retrieved without a proliferation of
* methods on the factory interface. These are arbitrary array indices,
* visible also to JNI code through the generated headers just as
* described above. The native initialization method may create,
* for example, an array of ByteBuffers that window the corresponding
* PostgreSQL globals, ordered according to these indices. The Java code
* implementing resourceOwner() can be ignorant of these specific values
* and simply use them to index the array. HOWEVER, it does know that
* the first one, index 0, refers to the current resource owner.
*/
protected static final int RSO_Current = 0; // must be index 0
protected static final int RSO_CurTransaction = 1;
protected static final int RSO_TopTransaction = 2;
protected static final int RSO_AuxProcess = 3;

protected abstract ResourceOwner resourceOwner(int which);

/*
* Same as above but for the well-known PostgreSQL MemoryContexts.
* Again, the implementing code knows index 0 is for the current one.
*/
protected static final int MCX_CurrentMemory = 0; // must be index 0
protected static final int MCX_TopMemory = 1;
protected static final int MCX_Error = 2;
protected static final int MCX_Postmaster = 3;
protected static final int MCX_CacheMemory = 4;
protected static final int MCX_Message = 5;
protected static final int MCX_TopTransaction = 6;
protected static final int MCX_CurTransaction = 7;
protected static final int MCX_Portal = 8;
/*
* A long-lived, never-reset context created by PL/Java as a child of
* TopMemoryContext.
*/
protected static final int MCX_JavaMemory = 9;

protected abstract MemoryContext memoryContext(int which);

protected abstract MemoryContext upperMemoryContext();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/*
* Copyright (c) 2022 Tada AB and other contributors, as listed below.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the The BSD 3-Clause License
* which accompanies this distribution, and is available at
* http://opensource.org/licenses/BSD-3-Clause
*
* Contributors:
* Chapman Flack
*/
package org.postgresql.pljava.model;

import org.postgresql.pljava.Lifespan;

import static org.postgresql.pljava.model.CatalogObject.Factory.*;

/**
* A PostgreSQL {@code MemoryContext}, which is usable as a PL/Java
* {@link Lifespan Lifespan} to scope the lifetimes of PL/Java objects
* (as when they depend on native memory allocated in the underlying context).
*<p>
* The {@code MemoryContext} API in PostgreSQL is described <a href=
"https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/utils/mmgr/README;hb=HEAD"
>here</a>.
*<p>
* Static getters for the globally known contexts are spelled and capitalized
* as they are in PostgreSQL.
*/
public interface MemoryContext extends Lifespan
{
/**
* The top level of the context tree, of which every other context is
* a descendant.
*<p>
* Used as described <a href=
"https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/utils/mmgr/README;hb=REL_14_0#l179"
>here</a>.
*/
MemoryContext TopMemoryContext =
INSTANCE.memoryContext(MCX_TopMemory);

/**
* The "current" memory context, which supplies all allocations made by
* PostgreSQL {@code palloc} and related functions that do not explicitly
* specify a context.
*<p>
* Used as described <a href=
"https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/utils/mmgr/README;hb=REL_14_0#l72"
>here</a>.
*/
static MemoryContext CurrentMemoryContext()
{
return INSTANCE.memoryContext(MCX_CurrentMemory);
}

/**
* Getter method equivalent to the final
* {@link #TopMemoryContext TopMemoryContext} field, for consistency with
* the other static getters.
*/
static MemoryContext TopMemoryContext()
{
return TopMemoryContext;
}

/**
* Holds everything that lives until end of the top-level transaction.
*<p>
* Can be appropriate when a specification, for example JDBC, provides that
* an object should remain valid for the life of the transaction.
*<p>
* Uses are described <a href=
"https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/utils/mmgr/README;hb=REL_14_0#l217"
>here</a>.
*/
static MemoryContext TopTransactionContext()
{
return INSTANCE.memoryContext(MCX_TopTransaction);
}

/**
* The same as {@link #TopTransactionContext() TopTransactionContext} when
* in a top-level transaction, but different in subtransactions (such as
* those associated with PL/Java savepoints).
*<p>
* Used as described <a href=
"https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/utils/mmgr/README;hb=REL_14_0#l226"
>here</a>.
*/
static MemoryContext CurTransactionContext()
{
return INSTANCE.memoryContext(MCX_CurTransaction);
}

/**
* Context of the currently active execution portal.
*<p>
* Used as described <a href=
"https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/utils/mmgr/README;hb=REL_14_0#l242"
>here</a>.
*/
static MemoryContext PortalContext()
{
return INSTANCE.memoryContext(MCX_Portal);
}

/**
* A permanent context switched into for error recovery processing.
*<p>
* Used as described <a href=
"https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/utils/mmgr/README;hb=REL_14_0#l247"
>here</a>.
*/
static MemoryContext ErrorContext()
{
return INSTANCE.memoryContext(MCX_Error);
}

/**
* A long-lived, never-reset context created by PL/Java as a child of
* {@code TopMemoryContext}.
*<p>
* Perhaps useful for PL/Java-related allocations that will be long-lived,
* or managed only from the Java side, as a way of accounting for them
* separately, as opposed to just putting them in {@code TopMemoryContext}.
* It hasn't been used consistently even in the historical PL/Java
* code base, and should perhaps be a candidate for deprecation (or for
* a thorough code review to establish firmer guidelines for its use).
*/
static MemoryContext JavaMemoryContext()
{
return INSTANCE.memoryContext(MCX_JavaMemory);
}

/**
* The "upper executor" memory context (that is, the context on entry, prior
* to any use of SPI) associated with the current (innermost) PL/Java
* function invocation.
*<p>
* This is "precisely the right context for a value returned" from a
* function that uses SPI, as described
* <a href="https://www.postgresql.org/docs/14/spi-memory.html">here</a>.
*/
static MemoryContext UpperMemoryContext()
{
return INSTANCE.upperMemoryContext();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright (c) 2022 Tada AB and other contributors, as listed below.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the The BSD 3-Clause License
* which accompanies this distribution, and is available at
* http://opensource.org/licenses/BSD-3-Clause
*
* Contributors:
* Chapman Flack
*/
package org.postgresql.pljava.model;

import org.postgresql.pljava.Lifespan;

import org.postgresql.pljava.model.CatalogObject.Factory;

import static org.postgresql.pljava.model.CatalogObject.Factory.*;

/**
* The representation of a PostgreSQL {@code ResourceOwner}, usable as
* a PL/Java {@link Lifespan Lifespan}.
*<p>
* The {@code ResourceOwner} API in PostgreSQL is described <a href=
"https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/utils/resowner/README;hb=HEAD"
>here</a>.
*<p>
* PostgreSQL invokes callbacks in phases when a {@code ResourceOwner}
* is released, and all of its built-in consumers get notified before
* loadable modules (like PL/Java) for each phase in turn. The release
* behavior of this PL/Java instance is tied to the
* {@code RESOURCE_RELEASE_LOCKS} phase of the underlying PostgreSQL object,
* and therefore occurs after all of the built-in PostgreSQL lock-related
* releases, but before any of the built-in stuff released in the
* {@code RESOURCE_RELEASE_AFTER_LOCKS} phase.
*/
public interface ResourceOwner extends Lifespan
{
static ResourceOwner CurrentResourceOwner()
{
return INSTANCE.resourceOwner(RSO_Current);
}

static ResourceOwner CurTransactionResourceOwner()
{
return INSTANCE.resourceOwner(RSO_CurTransaction);
}

static ResourceOwner TopTransactionResourceOwner()
{
return INSTANCE.resourceOwner(RSO_TopTransaction);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,14 @@
* methods on {@link Database Database} and {@link RegCollation RegCollation}.
* The one in use on the server (an often-needed value) is exposed by the
* {@link CharsetEncoding#SERVER_ENCODING SERVER_ENCODING} static.
*<h2>Lifespan subinterfaces</h2>
* Some PL/Java objects correspond to certain native structures in PostgreSQL
* and therefore must not be used beyond the native structures' lifespan.
* {@link Lifespan Lifespan} abstractly models any object in PostgreSQL that
* can be used to define, and detect the end of, a native-object lifespan.
* Two interfaces in this package that extend it and model specific PostgreSQL
* objects with that ability are {@link MemoryContext MemoryContext} and
* {@link ResourceOwner ResourceOwner}.
*<h2>TupleTableSlot, TupleDescriptor, and Adapter</h2>
*<p>
* {@code TupleTableSlot} in PostgreSQL is a flexible abstraction that can
Expand Down Expand Up @@ -136,3 +144,4 @@
package org.postgresql.pljava.model;

import org.postgresql.pljava.Adapter;
import org.postgresql.pljava.Lifespan;
2 changes: 1 addition & 1 deletion pljava-so/src/main/c/Backend.c
Original file line number Diff line number Diff line change
Expand Up @@ -757,7 +757,7 @@ static void initsequencer(enum initstage is, bool tolerant)
"and \"pljava-api.jar\" files, separated by the correct "
"path separator for this platform.")
));
pljava_DualState_unregister();
pljava_ResourceOwner_unregister();
_destroyJavaVM(0, 0);
goto check_tolerant;
}
Expand Down
Loading