Ponteiro em Java

Java não tem ponteiros, tem referencias. É IMPOSSIVEL Java ter ponteiros, dado que a máquina virtual java não tem essa capacidade.

Olha a droga da especificação e você vai ver que ela opera em cima de referencias entre objeto e não diz que precisa existir um heap no senso comum de programas C.

Agora oque a JVM da Sun faz na implementação dela, tanto faz, por que é uma implementação, não é a linguagem >>>Java<<<.

Quanto a class sun.misc.Unsafe; essa classe não acessa memoria ou tão pouco faz operações sob ponteiros. Ela é apenas uma classe de marcação para compilação semântica usada pela HotSpot. Ou seja, Java continua não tendo ponteiros.

Mas essa discussão está tão produtiva quanto argumentar se a parafina usada na produção do arroz foi refinada de óleo Brent ou WTI ou se for óleo sweet muda o gosto da mistura.

[quote=“louds”]Agora oque a JVM da Sun faz na implementação dela, tanto faz, por que é uma implementação, não é a linguagem >>>Java<<<.
[/quote]

Certo, veja a errata acima.

Ela te retorna o endereço físico (ponteiro) de um objeto na memória RAM, inclusive o endereço dos atributos de um objeto, para que eles possam ser acessados diretamente, não por eu e vc, mas por quem vai escrever APIs complexas como java.nio.

[color=red]Bomba: a classe Unsafe tem funções do tipo setMemory(address), putByte(address), getByte(address), ou seja, é possível através de um código 100% pure Java acessar diretamente um endereço físico de memória RAM.[/color]

Ou seja, se eu entro no JCP e proponho uma nova api java.lightspeedplane.*, eu posso trabalhar com ponteiros de memória via sun.misc.Unsafe. Pelo menos é o que me parece…

É aquilo. Falar que java não tem ponteiros é correto, mas as referencias não seriam ponteiros disfarçados e protegidos do programador ??? O que diferencia um ponteiro de uma referencia ??? Não vale falar que ponteiro vc pode fazer aritimética. Na minha cabeça a diferença é que uma referencia é protegida do programador e um ponteiro não. No resto é igual…

Uma referência não é um ponteiro por que ela não tem a mesma semântica. Vide as primeiras JVMs, onde as referências não eram ponteiros devido ao uso de um GC com copy/compact, elas eram índices para uma tabela de objetos.

Nao eh 100% Pure Java, justamente pelo fato de usar uma classe sun.*, diacho. E nao sou eu quem ta dizendo isso, eh a propria documentacao da Sun, que voce deveria ter lido quando eu te mandei o link :wink:

Como queriamos demonstrar, essa discussao nao tem o menor sentido :mrgreen:

100% pure Java está errado mesmo no meu contexto. Tem razão, cv. A frase certa é:

Bomba: a classe Unsafe tem funções do tipo setMemory(address), putByte(address), getByte(address), ou seja, é possível através de um código Java acessar diretamente um endereço físico de memória RAM.

Essa discussão ficou inútil mesmo. Peço desculpas pela minha teimosia. É que eu fiquei impressionado quando descobri esse sun.misc.Unsafe no código do Java NIO.

Câmbio desligo…

O Sergio está usando isso aqui http://wiki.yak.net/424 [color=red]CUIDADO AO VISITAR O LINK[/color]

Sergio, só para ser mais conclusivo, sun.misc.Unsafe não é java em nenhuma de suas possiveis formas. Sabe o porque? Ela tem métodos nativos que não são implementaveis via JNI.
De fato, o HotSpot quando encontra esses métodos os sustitui pelo código apropriado para usar ponteiros. Logo isso não é java nem a pau. A jikesrvm usa um mecanismo semelhante, caso queira estudar mais a fundo.

Olá

  1. Fortran tem referência desde sempre mesmo no tempo em que a gente acessava a memória diretamente sem toda esta questão de memória protegida e coisas assim. Mas Fortran pelo que eu saiba não tem ponteiros (pelo menos até antes do Fortran 77, pode ser que no 90 já tenha)

  2. Haver coisas com nome setMemory(address), set ou getByte(address) não quer dizer que seja acesso a memória direto e nem mesmo que tenha ponteiros. Quando eu uso ponteiro em C muitas coisas ocorrem por baixo dos panos antes que eu possa me convencer que estou acessando a memória diretamente, principalmente programando em WinNT/2000/XP. No DOS eu sabia que meus ponteiros estavam lá no segmento real abaixo de 640Kb.

  3. Ponteiro sem aritmética com ponteiros é a mesma coisa que um automóvel sem eixos, rodas, motor, carroceria, bancos, volante e adesivo do Framengo.

[]s
Luca

E, ainda bem, nao fez falta ate hoje - a manipulacao de arrays do Java, apesar de ainda ser bem lerdinha perto do que se estava acostumado a fazer em C, assembly ou outra linguagem pra macho, resolve todos os pepinos que so dava pra resolver com aritmetica de ponteiros – (d)efeitos especiais otimizados em imagens e FFTs, por exemplo. Alias, eu discordo do seu requerimento por um adesivo do mengao pra um automovel ser classificado como tal. :mrgreen:

O problema é que ponteiros são muito mais faceis de usar para navegar dentro de arrays que índices em Java. Seria muito legal se tivessemos um ArrayIterator que, assim como strings, tem operator overloading.

Enquanto em C você só passa o ponteiro, em java você precisa do array e do índice, 2x mais coisas.

int.iterator i = new int[10].iterator;
while(i) { //converte para boolean, indicando se ainda é válido para leitura
   System.out.println(*i); //desreferencia ele :)
}

Java deveria ter bounded pointers. :cry:

Senhor amado … contaminacao pura ,… hehehe

Ok pessoal,

vc estão falando de passagem por referência dentro da própria linguagem : de Java para Java , de C/C++ para C/C++.
E se for Java para C/C++???

Eu tenho a seguinte situação:
eu quero acessar objetos no Java pelo C via JNI usando passagem por referência pois o volume de dados pode ser imenso e eu não quero ter que fazer a JVM duplicar minhas variáveis na memória passando parâmetros por valor pra lá e pra cá.

O que acontece é que temos uma DLL desenvolvida em C e ela é utilizada em uma linguagem que aceita acesso direto a ponteiros, o que fazemos então é fornecer para a DLL os endereços dos valores a serem calculados e depois é só pegar os resultados.

Estamos estudando a migração do sistema para Java, vamos continuar usando essa DLL até que se tenha tempo e dimdim pra migrar toda o código.

Com JNI eu consigo acessar objetos Java e seus atributos,mas acho que ainda assim é por valor.
Vejam nesse código :

JNIEXPORT void JNICALL Java_com_Exemplo_metodo(JNIEnv *env, jobject obj_this){
jclass class_Exemplo = (*env)-&gt;GetObjectClass(env,obj_this);
jfiedID id_atributoA = (*env)-&gt;GetFieldID(env,class_Exemplo,&quot;atributoA&quot;,&quot;D&quot;);
jdouble atributoA = (*env)-&gt;GetDoubleField(env,obj_this,id_atributoA);

atributoA = atributoA * 2;
(*env)-&gt;SetDoubleField(env,obj_this,id_salario,salario);

Se para modificar uma variavel em uma classe java eu preciso usar o metodo SetXXXField isso cheira a passagem por valor. Na verdade só pode ser passagem por valor.

Na própria assinatura de um método JNI em C temos o parâmetro que referencia o ponteiro da estrutura JNIEnv, que faz referência ao endereço na memória a uma estrutura com as funções JNI da JVM. Isso é uma prova de que é possível utilizar passagem por referência entre Java e C.
Ta certo que é a própria implementação da JVM, é muito baixo nível, mas por mais baixo nível que seja, deve haver uma forma disponível para referenciar um endereço de memória.

....(JNIEnv *env,... 

Eu vi em algum lugar que isso se faz utilizando-se arrays, mas ainda não encontrei nenhum material esclarecedor que falasse sobre isso.

alguém manja???

A semântica da passagem de parâmetros não varia se você usa código nativo (public native etc…) ou não.

A passagem de objetos do Java para o Java, ou para o JNI/C++ é sempre passar uma referência por valor.

Não há cópia ou clonagem de objetos (passagem do OBJETO por valor).

Algo que é possível em C# mas não em Java, por exemplo, é passar uma referência por referência:

object obj = new object();
object obj2 = obj;
metodo (ref obj);
Console.WriteLine (obj2 == obj); // pode ser que obj seja modificado pelo método "metodo", apontando para um outro objeto, portanto nem sempre vai imprimir "true".

Mas em Java só é possível passar essa referência por valor:

Object obj = new Object();
Object obj2 = obj;
metodo (obj);
System.out.println (obj2 == obj); // A referencia a obj não pode ser modificada pelo método "metodo", portanto sempre vai imprimir "true".

Aqui tem algo. Basicamente, você tem que passar um array de tamanho 1 (se você passar um tipo primitivo, não consegue mudar o valor dentro da biblioteca em C, se passar um array, pode - eu acho isso gambiarra, mas funciona bem).
Nesse exemplo, você tem uma classe java que dobra o valor da variável:

public class DobraJNI {

	private static native void dobra (int[] n);
	static {
		System.loadLibrary("DobraDll");
	}

	public static void main (String[] args) {
		int[] i = Integer.parseInt(args[0]);
		System.out.print("2 x " + i[0] + " = ");
		dobra(i);
		System.out.println(i[0]);
	}
}

E agora, o código da biblioteca:

#include <jni.h>
#include "DobraJNI.h"

JNIEXPORT void JNICALL Java_DobraJNI_dobra (JNIEnv *env, jclass jc, jintArray anIntArray) {
  
	jint* valor;	

	valor = env->GetIntArrayElements (anIntArray, NULL);
	valor[0] *= 2;
	env->ReleaseIntArrayElements (anIntArray, valor, 0);
} 

Olha, sou novo do mundo do Java e já abandonei o C/C++, porem uma das vantagens que me lembro em relação ao uso de ponteiros em C/C++ era na passagem de parâmentros para algu método. Ponteiros deixava a tarefa mais rápida, visto que não era necessário passsar todo o “pacote” para o método. Mas e em Java como fica. Por exemplo: caso eu tenha que passar uma lista emcadeada com 500 nodos para um método, como faço???

Abraço a todos!!!

OBS: Essa postagem não é uma crítica a qualquer um dos envolvidos no diálogo. Apenas pergunto porque repito, sou novo no mundo do Java e tenho algumas dúvidas.

Essa discussão denovo
NNNNÃÃÃÃÃÃÃOOOOO…

rs rs rs rs

Sei que não devo “remexer o passado”, mas minha dúvida ainda não foi respondida!!!

vc tá passando só a referencia do objeto que está dentro do heap da vm

pode continuar a dormir tranquilo

e chega de ressuscitar posts!!! :twisted:

Ele só passa uma cópia do valor se o argumento for do tipo primitivo.
Mesmo que seja passado um array de primitivos, ele passa referência, pois um array é um objeto.

De modo geral, se você pensar bem como é que o Java funciona, ele trabalha mais com ponteiros que o próprio C++. Estranho? Não. É que em C++ é possível você passar objetos por valor:

#include &lt;string&gt;
using namespace std;
/**
 * Este método recebe a string de entrada, e retorna a mesma string, só que concatenada com a string "1":
 * @param s A string de entrada (copiada por valor)
 * @return A string de retorno.
 */
string appendOne (string s) {
    s = s + "1"; // isto não altera a string original :P
    return s;
}

E isso não é possível em Java - você só pode passar , por valor, uma referência a um objeto.

Mesmo sendo esse um tópico bem antigo faço questão de dar minha opinião.

No contexto de linguagens de programação, ponteiro é uma variável capaz de armazenar o endereço de outra variável.

Entrando no contexto de C++, ponteiro é também uma variável capaz de armazenar o endereço de outra variável E que permite a conhecida artimética de ponteiros.

Pensando dessa forma, analise a seguinte frase:

Java tem ponteiros que não permitem aritmética de ponteiros.

O que tem de errado nisso tudo?